hashMap 源码解析

1、构造方法

 1 public HashMap() {
 2         this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
 3     }
 4 
 5  public HashMap(int initialCapacity) {
 6         this(initialCapacity, DEFAULT_LOAD_FACTOR);
 7     }
 8 
 9  public HashMap(int initialCapacity, float loadFactor) {
10         if (initialCapacity < 0)
11             throw new IllegalArgumentException("Illegal initial capacity: " +
12                                                initialCapacity);
13         if (initialCapacity > MAXIMUM_CAPACITY)
14             initialCapacity = MAXIMUM_CAPACITY;
15         if (loadFactor <= 0 || Float.isNaN(loadFactor))
16             throw new IllegalArgumentException("Illegal load factor: " +
17                                                loadFactor);
18 
19         this.loadFactor = loadFactor;
20         threshold = initialCapacity;
21         init();
22     }
23 
24 public HashMap(Map<? extends K, ? extends V> m) {
25         this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
26                       DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
27         inflateTable(threshold);
28 
29         putAllForCreate(m);
30     }

4种构造方法

1、无参的构造方法,也就是我们最常用的构造方法,他给我们的默认的初始化 容量是16  也就是entry[]数组是16  ,entry 有什么参数? 

一共4个参数,key, value ,hash ,还有一个就是Entry<K,V> next 对象中的对象,负载因子默认是0.75

2、给一个数组大小的参数的是第二个构造函数

3、给两个的是上面所说的两个参数的构造函数,内容就是检验入参,最后的是初始化链表,这里是个空的方法,为的是子类要可以重写方法

put方法

//入参是key和value 
public V put(K key, V value) {
判断表中是不是没有数据
        if (table == EMPTY_TABLE) {
如果没有数据就调用这个方法(入参是容量* 负载因子)
            inflateTable(threshold);
        }
如果key 为空返回下面的方法。作用:
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        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;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }


/**
     * Inflates the table.
     */
    private void inflateTable(int toSize) {
        // 找到2的n次幂 >= 这个入参
例如:2^4>15 这个capacity =16
        int capacity = roundUpToPowerOf2(toSize);
获取合理的负载因子,
        threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
新建一个这么大的容量的数组并复给table
        table = new Entry[capacity];
//初始化哈希掩码值
        initHashSeedAsNeeded(capacity);
    }


//入参是插入进来的value
  private V putForNullKey(V value) {
循环这个数组的第一个数组 的链表,
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {
如果链表中的第一个值的 key值为空则把value值付给第一个原数的value
            if (e.key == null) {
                V oldValue = e.value;
                e.value = value;
//空方法
                e.recordAccess(this);
//返回老的value值,就是对数组做操作仅仅是变更了一下value值,
                return oldValue;
            }
        }
数组变更次数加一
        modCount++;
设置hash值为零,key值为null value为入参的值
        addEntry(0, null, value, 0);
        return null;


void addEntry(int hash, K key, V value, int bucketIndex) {
判断数组中的数据是否大于负载因子并且数组的第一个元素为空
        if ((size >= threshold) && (null != table[bucketIndex])) {
扩2被的数值长度
            resize(2 * table.length);

            hash = (null != key) ? hash(key) : 0;
            bucketIndex = indexFor(hash, table.length);
        }

入参是原来长度的2被
 void resize(int newCapacity) {
        Entry[] oldTable = table;
        int oldCapacity = oldTable.length;
如果超过最大了就直接返回不扩容了
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }
新建一个这么大的数组,
        Entry[] newTable = new Entry[newCapacity];
把老的数组中的数转换到新数组中
        transfer(newTable, initHashSeedAsNeeded(newCapacity));
        table = newTable;
        threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
    }


   void transfer(Entry[] newTable, boolean rehash) {
        int newCapacity = newTable.length;
循环原有的数组
        for (Entry<K,V> e : table) {
         循环每个链表
   while(null != e) {
                Entry<K,V> next = e.next;
                if (rehash) {
                    e.hash = null == e.key ? 0 : hash(e.key);
                }重置这个hash值,与运算,也就是获取一个位置,放到先新的数组中的位置
                int i = indexFor(e.hash, newCapacity);
                e.next = newTable[i];
                newTable[i] = e;
                e = next;
            }
        }
    }
想要体面生活,又觉得打拼辛苦;想要健康身体,又无法坚持运动。人最失败的,莫过于对自己不负责任,连答应自己的事都办不到,又何必抱怨这个世界都和你作对?人生的道理很简单,你想要什么,就去付出足够的努力。
原文地址:https://www.cnblogs.com/potentPrince/p/12557071.html