-
7中是Entry数组,8中是Node数组
-
7中数组中放的是链表,8中放的是红黑树或链表、
-
7扩容时是正序遍历原来的链表,将节点依次放在链表头,而8是正序遍历原来的链表,将节点放在链表尾;在并发的情况下,7可能出现并发死链的情况。
-
7扩容时在size > threshold的前提下,还要判断null!=table[bucketIndex],即判断要放的那个桶是不是为空,如果都满足,才扩容;而8只要满足size > threshold就扩容。
-
7在插入新节点时,是插在链表头的;8是插在链表尾的,还要判断是不是数量大于8,来决定是不是要树化;当然,7在插入前要遍历链表,来确定不会key重复;8则遍历到最后,然后插入
//jdk7的put
public V put(K key, V value) {
//如果数组为空,则新建数组
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
//如果key为null,则把value放在table[0]中
if (key == null)
return putForNullKey(value);
//生成key所对应的hash值
int hash = hash(key);
//根据hash值和数组的长度找到:该key所属entry在table中的位置i
int i = indexFor(hash, table.length);
/**
* 数组中每一项存的都是一个链表,
* 先找到i位置,然后循环该位置上的每一个entry,
* 如果发现存在key与传入key相等,则替换其value。然后结束侧方法。
* 如果没有找到相同的key,则继续执行下一条指令,将此键值对存入链表头
*/
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
//map操作次数加一
modCount++;
//查看是否需要扩容,并将该键值对存入指定下标的链表头中
addEntry(hash, key, value, i);
//如果是新存入的键值对,则返回null
return null;
}