从源码真正的了解HashMap
- 我们先来看看HashMap提供的构造方法有哪些?
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);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
- 该方法指定初始容量以及装载因子,常量MAXIMUM_CAPACITY = 1 << 30为HashMap的最大容量
- 这里注意到方法tableSizeFor(),这个方法返回的值是最接近initialCapacity值的2的幂,并且会把这个值存储在threshold中。
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;//>>>代表无符号右移
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
- 该方法只指定初始容量大小,DEFAULT_LOAD_FACTOR = 0.75f为HashMap默认的装载因子,当HashMap中的元素数量超过容量*0.75的时候,要进行resize()操作,也就是HashMap的扩容。
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
- 该方法所有参数均用默认值。
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}
- 该方法传进来一个Map来创建,在下面介绍。
HashMap 的put方法
在看put方法前,先了解一下HashMap中定义的各种变量的作用
static final int TREEIFY_THRESHOLD = 8;
- hash 冲突的链表向红黑树转变的临界值
static final int UNTREEIFY_THRESHOLD = 6;
- hash 冲突的红黑树转变为链表的临界值
static final int MIN_TREEIFY_CAPACITY = 64;
- 当需要将链表转为红黑树时,需要判断当前数组的容量,如果当前的容量小于MIN_TREEIFY_CAPACITY,则要进行扩容操作,不进行转变操作。
transient Node<K,V>[] table;
- 保存节点的数组
transient Set<Map.Entry<K,V>> e