源码分析八( hashmap工作原理)

首先从一条简单的语句开始,创建了一个hashmap对象:

 Map<String,String> hashmap = new HashMap<String,String>(); 

调用hashmap类无参数构造方法,使用默认转载因子,

1 public HashMap() {
2         this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
3     }

默认装载因子只有在构造器不指定的情况下使用

1 /**
2      * The load factor used when none specified in constructor.
3      */
4     static final float DEFAULT_LOAD_FACTOR = 0.75f;

hashmap还有三个重载的构造方法,分别是:

有装载因子入参的构造方法

1 public HashMap(int initialCapacity) {
2         this(initialCapacity, DEFAULT_LOAD_FACTOR);
3     }

有初始化容器容量以及装载因子的构造方法

 1 public HashMap(int initialCapacity, float loadFactor) {
 2         //如果初始容量小于0,则抛出非法初始化容量异常
 3         if (initialCapacity < 0)
 4             throw new IllegalArgumentException("Illegal initial capacity: " +
 5                                                initialCapacity);
 6         //如果初始容量大于最多容量,则容量为最多容量
 7         if (initialCapacity > MAXIMUM_CAPACITY)
 8             initialCapacity = MAXIMUM_CAPACITY;
 9         //如果装载因子不大于0或者装载因子不是数字,则抛出装载因子非法异常
10         if (loadFactor <= 0 || Float.isNaN(loadFactor))
11             throw new IllegalArgumentException("Illegal load factor: " +
12                                                loadFactor);
13         this.loadFactor = loadFactor;
14         //根据初始化容量计算hashmap的阈值容量(hashmap真正的容量,必须是2的次方)
15         this.threshold = tableSizeFor(initialCapacity);
16      }

计算hashmap的容量

 1 // 根据给定的目标容量,计算一个2的次方
 2     static final int tableSizeFor(int cap) {
 3         int n = cap - 1;
 4         n |= n >>> 1;
 5         n |= n >>> 2;
 6         n |= n >>> 4;
 7         n |= n >>> 8;
 8         n |= n >>> 16;
 9         return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
10     }

有参数map的构造方法:

1 public HashMap(Map<? extends K, ? extends V> m) {
2             this.loadFactor = DEFAULT_LOAD_FACTOR;
3             putMapEntries(m, false);
4      }

将map复制一份到本地,这个复制如果对于数值型则为数值,对于引用型则为地址

 1 final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
 2         int s = m.size();
 3         //原来map的长度大于0处理
 4         if (s > 0) {
 5             if (table == null) { // pre-size
 6                 //根据实际数量计算需要多大的容量
 7                 float ft = ((float) s / loadFactor) + 1.0F;
 8                 int t = ((ft < (float) MAXIMUM_CAPACITY) ? (int) ft : MAXIMUM_CAPACITY);
 9                 //如果预估容量大于现有容量,则需要根据预估容量计算一个2的次方数
10                 if (t > threshold)
11                     threshold = tableSizeFor(t);
12             }
13             //如果实际容量大于阈值则需要扩容
14             else if (s > threshold)
15                 resize();
16             //扩容之后,将m的key和value复制一份到本地
17             for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
18                 K key = e.getKey();
19                 V value = e.getValue();
20                 putVal(hash(key), key, value, false, evict);
21             }
22         }
23     }
 1 //第一次调用初始化或者扩容
 2     final Node<K,V>[] resize() {
 3         //首次调用时为null,则oldCap为0 | 扩容时,
 4         Node<K,V>[] oldTab = table;
 5         int oldCap = (oldTab == null) ? 0 : oldTab.length;
 6         int oldThr = threshold;
 7         int newCap, newThr = 0;
 8         //扩容时,如果目前容量已经超过最多容量,那么默认值为int最大,否则容量为现在2倍
 9         if (oldCap > 0) {
10             if (oldCap >= MAXIMUM_CAPACITY) {
11                 threshold = Integer.MAX_VALUE;
12                 return oldTab;
13             }
14             else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
15                      oldCap >= DEFAULT_INITIAL_CAPACITY)
16                 newThr = oldThr << 1; // double threshold
17         }
18         //初始化时newCap = oldThr = threshold
19         else if (oldThr > 0) // initial capacity was placed in threshold
20             newCap = oldThr;
21         else {               // zero initial threshold signifies using defaults
22             newCap = DEFAULT_INITIAL_CAPACITY;
23             newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
24         }
25         //初始化时newThr=newCap * loadFactor
26         if (newThr == 0) {
27             float ft = (float)newCap * loadFactor;
28             newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
29                       (int)ft : Integer.MAX_VALUE);
30         }
31         threshold = newThr;
32         @SuppressWarnings({"rawtypes","unchecked"})
33         //初始化时,创建一个长度为threshold的Node数组,然后返回
34             Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
35         table = newTab;
36         if (oldTab != null) {
37             for (int j = 0; j < oldCap; ++j) {
38                 Node<K,V> e;
39                 if ((e = oldTab[j]) != null) {
40                     oldTab[j] = null;
41                     if (e.next == null)
42                         newTab[e.hash & (newCap - 1)] = e;
43                     else if (e instanceof TreeNode)
44                         ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
45                     else { // preserve order
46                         Node<K,V> loHead = null, loTail = null;
47                         Node<K,V> hiHead = null, hiTail = null;
48                         Node<K,V> next;
49                         do {
50                             next = e.next;
51                             if ((e.hash & oldCap) == 0) {
52                                 if (loTail == null)
53                                     loHead = e;
54                                 else
55                                     loTail.next = e;
56                                 loTail = e;
57                             }
58                             else {
59                                 if (hiTail == null)
60                                     hiHead = e;
61                                 else
62                                     hiTail.next = e;
63                                 hiTail = e;
64                             }
65                         } while ((e = next) != null);
66                         if (loTail != null) {
67                             loTail.next = null;
68                             newTab[j] = loHead;
69                         }
70                         if (hiTail != null) {
71                             hiTail.next = null;
72                             newTab[j + oldCap] = hiHead;
73                         }
74                     }
75                 }
76             }
77         }
78         return newTab;
79     }
原文地址:https://www.cnblogs.com/warrior4236/p/9135394.html