HashMap源码分析
源码分析
一.construct
public HashMap(int initialCapacity, float loadFactor) {
//valid loadFactor ...
this.loadFactor = loadFactor;
//计算容量
this.threshold = tableSizeFor(initialCapacity);
}
二.tableSizeFor
/**
* Returns a power of two size for the given target capacity.
*/
static final int tableSizeFor(int cap) {
//排查已经是2^n
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
//分析
/**
* 0000 001x xxxx xxxx //假设任意二进制数,查找比它大,且是2^n的数
* 0000 0100 0000 0000 //一定会得到这个值,以为每个位数都是2^n
* n|n>>>1
* n|n>>>2
* n|n>>>4
* n|n>>>8
* n|n>>>16 //保证所有的数字都被覆盖
* 最终结果
* 0000 0111 1111 1111 //+1即可
*/
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
三.put
//1
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
//2
static final int hash(Object key) {
int h;
/**
* 扰动函数
* 包含高位地位的信息 -减少碰撞
* 0abc defg hijk lmno
* 0000 0000 0abc defg
* ---或运算--
*/
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
//3
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
// 如果桶容量为0,则初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//如果根据hash计算下标的位置没有元素则直接放置该位置
//(n-1)&hash 定位
//(2n-1)&hash 扩容重新定位(所以resize时,要么原位置,要么要位置2倍)
//
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
//如果桶中第一个元素与插入元素key的hash相同,则将该点保存在e中
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
//如果是树,则putTreeVal
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
//如果遍历完毕,key不存在,则插入链表最后一个节点
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
//树化
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
//如果找到了key对应的元素
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
先读这么多吧...