精英联盟总队|面试官:说一下HashMap原理,为什么会产生死循环


精英联盟总队|面试官:说一下HashMap原理,为什么会产生死循环Map 这样的 Key Value 在软件开发中是非常经典的结构 , 常用于在内存中存放数据 。 众所周知 HashMap 底层是基于 数组 + 链表 组成的 , 不过在 JDK1.7 和 1.8 中具体实现稍有不同 。
今天我们只讲解JDK1.7版本的HashMap 。
1、HashMap的数据结构图是一个数组+链表结构
精英联盟总队|面试官:说一下HashMap原理,为什么会产生死循环2、HashMap成员变量/** * The default initial capacity - MUST be a power of two. */static final int DEFAULT_INITIAL_CAPACITY = 16;/** * The maximum capacity, used if a higher value is implicitly specified * by either of the constructors with arguments. * MUST be a power of two <= 1<<30. */static final int MAXIMUM_CAPACITY = 1 << 30;/** * The load factor used when none specified in constructor. */static final float DEFAULT_LOAD_FACTOR = 0.75f;/** * The table, resized as necessary. Length MUST Always be a power of two. */transient Entry[] table;/** * The number of key-value mappings contained in this map. */transient int size;/** * The next size value at which to resize (capacity * load factor). * @serial */int threshold;/** * The load factor for the hash table. * * @serial */final float loadFactor;这是 HashMap 中比较核心的几个成员变量;看看分别是什么意思?
① DEFAULT_INITIAL_CAPACITY :初始化桶大小(16) , 因为底层是数组 , 所以这是数组默认的大小 。
② MAXIMUM_CAPACITY :桶最大值 。
③ DEFAULT_LOAD_FACTOR :默认的负载因子(0.75)
④ table:真正存放数据的数组 。
⑤ size:map中存放的键值对的数量 。
⑥ threshold:resize扩容时的阈值 。
⑦ loadFactor:负载因子 , 可在初始化时显式指定 。
HashMap 的构造函数可以指定参数也可以无参:
public HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR;threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);table = new Entry[DEFAULT_INITIAL_CAPACITY];init();}public HashMap(int initialCapacity) {this(initialCapacity, DEFAULT_LOAD_FACTOR);}public HashMap(int initialCapacity, float loadFactor) {if (initialCapacity < 0)throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity);if (initialCapacity > MAXIMUM_CAPACITY)initialCapacity = MAXIMUM_CAPACITY;if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new IllegalArgumentException("Illegal load factor: " +loadFactor);// Find a power of 2 >= initialCapacityint capacity = 1;while (capacity < initialCapacity)capacity <<= 1;this.loadFactor = loadFactor;threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);table = new Entry[capacity];useAltHashing = sun.misc.VM.isBooted()init();}默认容量为 16 , 负载因子为 0.75 。 Map 在使用过程中不断的往里面存放数据 , 当数量达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容 , 而扩容这个过程涉及到 rehash、复制数据等操作 , 所以非常消耗性能 。
因此通常建议能提前预估 HashMap 的大小最好 , 尽量的减少扩容带来的性能损耗 。
3、Entry类根据代码可以看到真正存放数据的是:transient Entry


推荐阅读