hashmap的put和get方法

盗了张图,结合源码看很清晰:

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        //定义一个数组,一个链表,n永远存放数组长度,i用于存放key的hash计算后的值,即key在数组中的索引
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
       //根据key进行hash与数组最大值进行与运算判断位子,当前key所在的索引值,并且将当前索引上的 
       //Node赋予给p并判断是否该Node是否存在
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
       //进入这里说明索引位置已经放入过数据了
            Node<K,V> e; K k;
       //判断put的数据和之前的数据是否重复(比较桶中第一个元素(数组中的结点)的hash值相等,key相等)
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))   
       //key的地址或key的equals()只要有一个相等就认为key重复了,就直接覆盖原来key的value
                e = p;
       //判断是否是红黑树,如果是红黑树就直接插入树中
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
       //如果不是红黑树,就遍历每个节点,判断链表长度是否大于8,如果大于就转换为红黑树
                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是否可要插入的key相同,如果相同就直接覆盖
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
//如果e不是null,说明没有迭代到最后就跳出了循环,说明链表中有相同的key,因此只需要将value覆盖,并将oldValue返回即可
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
//说明没有key相同,因此要插入一个key-value,并记录内部结构变化次数
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
//如果表不是空的,并且要查找索引处有值,就判断位于第一个的key是否是要查找的key
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
//如果是,就直接返回
                return first;
//如果不是就判断链表是否是红黑二叉树,如果是,就从树中取值
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
//如果不是树,就遍历链表
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }

猜你喜欢

转载自blog.csdn.net/weixin_40403930/article/details/89298742