集合

1.HashMap

1)put()的执行过程:

/**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with {@code key}, or
     *         {@code null} if there was no mapping for {@code key}.
     *         (A {@code null} return can also indicate that the map
     *         previously associated {@code null} with {@code key}.)
     */
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

    /**
     * Implements Map.put and related methods.
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
    //1. 判断entry数组是否为空或者长度为为0,若是则resize()
if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length;
    //2. 根据新key的hash在entry数组中查找对应位置的第一个元素p,若该元素为空则直接插入key和value
if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null);
    //3.若该元素不为空,说明发生了hash冲突
else { Node<K,V> e; K k;
      //3.1 如果p的hash和新key的hash相同,且两者的key相当(==或equals()为true),就直接用新value替换掉旧的value。
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p;
        //3.2 如果p的hash和新key的hash、p的key和新key,这两组至少有一组不相同,且p是红黑树节点,则将新key和新value插入到红黑树。
else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        //3.3 如果p的hash和新key的hash、p的key和新key,这两组至少有一组不同,且p不是红黑树节点,则说明p是链表头,就遍历p这个链表,若找到hash和key均相等的元素就退出遍历并将新value替换旧value。若整个链表均不存在这样的元素
          //就在链表的尾部插入新元素。若遍历时发现链表长度超过8,就将链表转换为红黑树。
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; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } 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; }

 

posted @ 2020-10-27 21:05  日进一卒  阅读(130)  评论(0)    收藏  举报