HashMap源码阅读(2)-put操做

1java

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
    int h;
    //k求的hashCode后, 高16位和低16位作异或运算(同则0,异则1,11->0,00->0, 10->1)
    //为何呢?减小碰撞.
    //为何能减小碰撞?
    /*
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null)
     */
    // n 是2的幂次方, 所以n-1的二进制,除了符号位是0,其余都是1; 由于作&运算后结果的离散性,取决于hash值的离散性
    // 生活中都有规律,使用的key要么通常偏小(整型,可能是short),要么偏大(长字符串的hash). 高低8位作异或,打破规律.(本身胡诌的.......)
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); //无符号右移16位,高位补0
  //  111111111 11111111 11111111 11111111 ^ 00000000 00000000 00000000 01111001
    //
}
/*
1 首次插入,要初始化table,分配空间
2 是否有碰撞:
    a 无,则插入
    b 有,则须要遍历链表(或红黑树)查找是否存在相同的key [ 碰撞耗费性能 ]
       ba: 存在相同的key-> 替换
       bb: 不存在相同的key,插入尾部
 */
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node<K,V>[] tab; Node<K,V> p; int n, i;

    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;// 1 HashMap是lazy的.第一次put时,才调用resize,初始化table,分配空间
    // 若是未发生碰撞
    if ((p = tab[i = (n - 1) & hash]) == null) //用&运算来求余,提升效率
        tab[i] = newNode(hash, key, value, null);
    else { //若是发生碰撞
        Node<K,V> e; K k;
        if (p.hash == hash && // 若是key的hash值相同,且equals(或同一内存地址->同一对象)
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p; //对value进行替换
        // 若是是红黑树节点
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            //若是是链表,遍历链表
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {//到了链表末尾
                    p.next = newNode(hash, key, value, null);//链表末尾新增一个节点
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);// 链表节点数超过阈值,将其转换成为红黑树
                    break;
                }

                // 遍历链表,查找是否有key相同的元素
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break; //若是有,则break, 此时e为key相同的节点
                p = e;
            }
        }
        if (e != null) { // existing mapping for key
            V oldValue = e.value; // 对value作替换
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue; //返回旧的value
        }
    }
    ++modCount;//对修改次数加1
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
}
相关文章
相关标签/搜索