public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
1.源码预热篇
Hash(key)-->对key的值进行了一种计算,然后得到一个int类型的-->是对该简直对进行一个下标位置的计算。
Key value进行存储的话,使用的数据结构是什么?
集合:ArrayList和LinkedLinst。
HashMap既想要查询的效率快,也想要增删的效率高。
2.源码猜想片
能不能结合一下数组和链表的优势,所以我们能推出HashMap源码地城数据结构是采用的链表+数组的形式。
(1)HashMap源码中Key,value存储的单元是什么。
java是一门面向对象的开发语言,
class DuiXiang<K,V>{
private K key;
private V value;
private Node next;
}
(2)数组该怎么表示?
int String int[] String[]
Node<K,V>[ ]
(3)数组要不要有一个大小呢?
初始大小?
上限大小?
(4)大小的一个解决方案。
假设初始大小是16,如果数组的大小不够用,或则达到了某个值,是不是要进行数组大小的扩容。
final Node<K,V>[] resize(){}
扩容是不是要有一个依据?16 数组大小已经达到了12的时候,就要进行数组大小的一个扩容。
Totalsize=16
数组目前使用的大小size
sieze>totalsize*小于1的小数,3/4
(5)链表的长度是不是也要有一个限制呢?
达到一个限制值之后,也需要进行一个改变?
jdk1.8的时候,如果链表的长度大于某个值,就将其结构改成红黑树。
TREEIFY_THRESHOLD=8
阈值
(6)新来的Node节点到底存在哪里?
存在哪里就要有一个约束,这个约束通过我们的一个计算的来的
key value
利用这个key进行一个计算,计算出这个Node到底应该存在哪里。
解决办法:Hash函数 hash(key)-->得到理性的值
3.源码分析篇
(1)put
putval()
(2)Putval()
hash(key)
(3)因为我要知道这个key value到底存在HashMap结构中的哪里。
key的值去计算
hash函数。
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
充分的利用int类型的32为数,全部应用起来的,
该数的高16位 低16位
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
Node<K,V>[] tab; Node<K,V> p; int n, i;
N记录变量数组大小
初始化数组
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
Node[ ] table = new Node[ defautl]
int threshold : 容量*负载因子 16*0.75 =12
if ((p = tab[i = (n - 1) & hash]) == null)
//tab[数值]
要保证这个下表不能超过n if(hash>n)
数组的散列性就大,碰撞概率就低了
数组大小一定是2的N次幂