Java集合框架:HashMap

今天复习到了HashMap,感觉好多东西都忘记了。所以去把源码看了一遍,把有些东西记了下来并注释了一下。

类:

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable 

 主要属性:

//序列号
    private static final long serialVersionUID = 362498820763181265L;
    //默认初始化容量=16
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    //最大容量
    static final int MAXIMUM_CAPACITY = 1 << 30;
    /**
     * The load factor used when none specified in constructor.
     */
    //填充因子
    static final float DEFAULT_LOAD_FACTOR = 0.75f;
    
    //当桶上的节点大于这个数值时候变成红黑树
    static final int TREEIFY_THRESHOLD = 8;

    /**
     * The bin count threshold for untreeifying a (split) bin during a
     * resize operation. Should be less than TREEIFY_THRESHOLD, and at
     * most 6 to mesh with shrinkage detection under removal.
     */
    //当桶上的节点小于这个数值时候红黑树转成链表
    static final int UNTREEIFY_THRESHOLD = 6;

    /**
     * The smallest table capacity for which bins may be treeified.
     * (Otherwise the table is resized if too many nodes in a bin.)
     * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts
     * between resizing and treeification thresholds.
     */
    //桶中结构由数组变成红黑树时候table数组的最小大小为这个值(4倍桶阙值)
    //意思:当数组的长度小于64,但是table[i]上的节点数已经大于等于8了,它不会先转化为红黑树,而是先扩容。只有数组长度大于64,并且节点数量大于等于8才转化为红黑树结构。        
    static final int MIN_TREEIFY_CAPACITY = 64;//存放元素的数组,总是2的幂次倍
transient Node<K,V>[] table;

//存放具体元素的集合
transient Set<Entry<K,V>> entrySet;

//实际大小
transient int size;

//扩容和更改map结构的计数器
transient int modCount;

/**
 * The next size value at which to resize (capacity * load factor).
 */
//扩容阙值:当size>=threshold(threshold=capacity * load factor)将会进行扩容
int threshold;
//hash table的负载因子,loadFactor越接近1,说明数组存放的entry数据越多。 DEFAULT_LOAD_FACTOR = 0.75f;
final float loadFactor;

桶上的节点类

     static class Node<K,V> implements Entry<K,V> {
        final int hash;//hash值,元素之间的比较值
        final K key;//
        V value;//
        Node<K,V> next;//指向下一个节点,说明是用单链表实现的

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }
        //重写了hashCode()方法,返回key和value的hash值的异或值
        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }
        //重写了equals()方法
        public final boolean equals(Object o) {
            if (o == this)
                return true;
            //如果o是Entry类的实例,则
            if (o instanceof Entry) {
                Entry<?,?> e = (Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }    

扩容规则:

旧容量*2。

if (oldCap > 0) {
            //如果旧的数组容量大于最大阙值,就不进行扩容,直接返回旧数组
            if (oldCap >= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }
            //如果旧的容量*2小于最大容量(64),扩容大小为2倍
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                     oldCap >= DEFAULT_INITIAL_CAPACITY)
                newThr = oldThr << 1; // double threshold
        }

 

posted @ 2019-01-01 20:52  发包哥哥  阅读(169)  评论(0编辑  收藏  举报