JDK源碼分析系列_HashMap

源碼分析:java

 1 package java.util;  2 
 3 import java.io.IOException;  4 import java.io.InvalidObjectException;  5 import java.io.Serializable;  6 import java.lang.reflect.ParameterizedType;  7 import java.lang.reflect.Type;  8 import java.util.function.BiConsumer;  9 import java.util.function.BiFunction;  10 import java.util.function.Consumer;  11 import java.util.function.Function;  12 
 13 /*
 14 底層基於散列算法實現,散列算法分爲散列再探測和拉鍊式,HashMap-->拉鍊式  15 HashMap並不保證鍵值對的順序,這意味着在進行某些操做後,鍵值對的順序可能會發生變化。  16 HashMap的key必須是immutable(String、Integer)的,key能夠用自定義的對象,可是自實現的類必須重寫equals  17 和hashcode方法  18 
 19 JDK1.8HashMap的優化:  20 1.引入紅黑樹解決過長鏈表效率低的問題  21 2.重寫resize方法,移除了alternative hashing相關方法,避免從新計算鍵的hash  22 
 23 哈希衝突的解決方法:  24 1.開放定址法(線性探測再散列,二次探測再散列,僞隨機探測再散列)  25 2.再哈希法,就是在原hash函數的基礎,再次執行hash算法  26 3.鏈地址法,各類處理哈希碰撞的方法中,這種最簡單  27 4.創建一個公共溢出區  28 
 29 HashMap的線程不安全體如今:  30 1.多線程同時put添加元素會丟失元素  31 2.多線程同時擴容會形成死循環  32 
 33 HashMap與Hashtable的區別:  34 1.HashMap線程不安全,Hashtable線程安全  35 2.HashMap能夠存null鍵null值(在計算哈希值時,null鍵哈希值爲0),Hashtable不能夠  36 3.HashMap去掉了Hashtable中的contains方法,改成了containsKey和containsValue  37 4.Hashtable繼承自陳舊的Dictionary類,而HashMap是JDK1.2引進的Map的一個實現  38 5.Hashtable中hash數組默認大小爲11,擴容方式爲old*2+1,HashMap中hash數組默認大小是16,擴容方式爲old*2  39 6.hash算法不同,Hashtable是除留餘數法,HashMap是h = key.hashCode()) ^ (h >>> 16,映射到數組爲hash&(n-1)  40 7.HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的  41  */
 42 public class HashMap<K,V> extends AbstractMap<K,V>
 43     implements Map<K,V>, Cloneable, Serializable {  44     private static final long serialVersionUID = 362498820763181265L;  45     /*
 46  默認初始化容量爲16,HashMap的容量必須是2的整次冪(必定是合數),這是一種  47  很是規的設計,常規的設計是把桶的大小設計爲素數,相對來講素數致使衝突的機率  48  要小於合數。Hashtable初始化桶的大小爲11,擴容機制爲擴容前容量乘以2加1。  49  HashMap這種很是規的設計主要是爲了在取模和擴容時做優化,同時爲了減小衝突  50      */
 51     static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  52     //最大容量爲2^30
 53     static final int MAXIMUM_CAPACITY = 1 << 30;  54     /*
 55  負載因子設置高雖然能夠減小空間開銷,可是會增長查詢時間,  56  默認負載因子0.75是在時間和空間成本上的tradeoff,負載因子能夠大於1  57      */
 58     static final float DEFAULT_LOAD_FACTOR = 0.75f;  59     /*
 60  鏈表長度>=8,轉換爲紅黑樹。有人可能會有疑問,爲何到8才轉換?主要是由於紅黑樹的平均查找長度是log(n),  61  長度爲8時,平均查找長度是3。若是繼續使用鏈表,平均查找長度爲8/2=4,這纔有轉換爲樹的必要。  62     */
 63     static final int TREEIFY_THRESHOLD = 8;  64     /*
 65  長度爲6時,樹轉鏈表。中間有個差值的緣由是防止鏈表和樹頻繁轉換。假設8以上轉爲樹,8如下轉爲鏈表,那麼一個  66  HashMap若是不停的插入刪除,長度在8左右徘徊,就會不停的樹轉鏈表,鏈表轉樹,效率很低。  67     */
 68     static final int UNTREEIFY_THRESHOLD = 6;  69     //最小的紅黑樹容量爲64
 70     static final int MIN_TREEIFY_CAPACITY = 64;  71     //基礎的桶節點(bin node)
 72     static class Node<K,V> implements Map.Entry<K,V> {  73         final int hash;  74         final K key;  75  V value;  76         Node<K,V> next;  77 
 78         Node(int hash, K key, V value, Node<K,V> next) {  79             this.hash = hash;  80             this.key = key;  81             this.value = value;  82             this.next = next;  83  }  84 
 85         public final K getKey()        { return key; }  86         public final V getValue()      { return value; }  87         public final String toString() { return key + "=" + value; }  88 
 89         public final int hashCode() {  90             return Objects.hashCode(key) ^ Objects.hashCode(value);  91  }  92 
 93         public final V setValue(V newValue) {  94             V oldValue = value;  95             value = newValue;  96             return oldValue;  97  }  98 
 99         public final boolean equals(Object o) {  100             if (o == this)  101                 return true;  102             if (o instanceof Map.Entry) {  103                 Map.Entry<?,?> e = (Map.Entry<?,?>)o;  104                 if (Objects.equals(key, e.getKey()) &&
 105  Objects.equals(value, e.getValue()))  106                     return true;  107  }  108             return false;  109  }  110  }  111     /* ---------------- Static utilities -------------- */
 112 
 113     /*
 114  擾動函數 不少人可能不理解爲何要和h>>>16做一次異或,下面給出詳細的解釋:  115  因爲散列值是int類型的,若是直接拿散列值做爲下標訪問HashMap主數組的話,考慮到32位有符號的int值的範圍從  116  -2147483648到214748364,先後加起來大概40億的映射空間。那麼問題來了,一個40億長度的數組,內存是放不下  117  的,因此這個散列值是不能拿過來直接用的,JDK中經過(n-1)&hash這樣的操做獲得訪問數組的下標。(實際上這個操  118  做在n爲2的整次冪時就等於hash%n)這也解釋了爲何HashMap的數組長度要取2的整次冪,由於這樣(數組長度-1)正  119  好至關於一個「低位掩碼」,與的結果就是散列值的高位清零,只保留低位值用來做數組下標。以初始長度16爲例,16-1  120  =15。二進制表示爲00000000 00000000 00000000 00001111,和某散列值做與運算,結果就是截取了最低的4位值。  121  10101010 10010101 10001110 00100101  122  & 00000000 00000000 00000000 00001111  123  ---------------------------------------  124  00000000 00000000 00000000 00000101 //高位所有清零,只保留末4位  125  那麼問題又來了,就算散列值分佈的再分散,要是隻取最後幾位的話,碰撞也會很嚴重。這時和h>>>16做一次異或的價值  126  就體現出來了。  127  h=key.hashCode(): 1111 1111 1111 1111 1111 0000 1110 1010 //調用hashCode()  128  ---------------------------------------------------------  129  h: 1111 1111 1111 1111 1111 0000 1110 1010  130  h>>>16: 0000 0000 0000 0000 1111 1111 1111 1111 //計算hash  131  hash=h^(h>>>16): 1111 1111 1111 1111 0000 1111 0001 0101  132  ---------------------------------------------------------  133  (n-1)&hash: 0000 0000 0000 0000 0000 0000 0000 1111  134  1111 1111 1111 1111 0000 1111 0001 0101 //計算下標  135  0000 0000 0000 0000 0000 0000 0000 0101=5  136  ---------------------------------------------------------  137  右移16位,正好是32位的一半,本身的高半區和低半區做異或,就是爲了混合原始散列值的高位和低位,使混合後的低位摻  138  雜了高位的部分特徵,以此來提升低位的隨機性,從而能夠有效下降碰撞次數。  139     */
 140     static final int hash(Object key) {  141         int h;  142         return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);  143  }  144     /*
 145  經過反射機制判斷對象x是否實現Comparable接口  146  若是實現了Comparable,返回x的實際類型,不然返回null  147     */
 148     static Class<?> comparableClassFor(Object x) {  149         if (x instanceof Comparable) {  150             Class<?> c; Type[] ts, as; Type t; ParameterizedType p;  151             if ((c = x.getClass()) == String.class)  152                 return c;  153             if ((ts = c.getGenericInterfaces()) != null) {  154                 for (int i = 0; i < ts.length; ++i) {  155                     if (((t = ts[i]) instanceof ParameterizedType) &&
 156                         ((p = (ParameterizedType)t).getRawType() ==
 157                          Comparable.class) &&
 158                         (as = p.getActualTypeArguments()) != null &&
 159                         as.length == 1 && as[0] == c)  160                         return c;  161  }  162  }  163  }  164         return null;  165  }  166 
 167     @SuppressWarnings({"rawtypes","unchecked"})  168     static int compareComparables(Class<?> kc, Object k, Object x) {  169         return (x == null || x.getClass() != kc ? 0 :  170  ((Comparable)k).compareTo(x));  171  }  172     /*
 173  返回不小於cap的最小的2的整次冪  174  假設cap = 5  175  n = cap - 1 = 4 = 0 1 0 0  176  n |= n >>> 1; 0 1 0 0 | 0 0 1 0 = 0 1 1 0 = 6  177  n |= n >>> 2; 0 1 1 0 | 0 0 0 1 = 0 1 1 1 = 7  178  n |= n >>> 4; 0 1 1 1 | 0 0 0 0 = 0 1 1 1 = 7  179  n |= n >>> 8; 0 1 1 1 | 0 0 0 0 = 0 1 1 1 = 7  180  n |= n >>> 16; 0 1 1 1 | 0 0 0 0 = 0 1 1 1 = 7  181  return n + 1 7 + 1 = 8  182  有人可能不理解爲何要對cap做-1的預處理,下面給出解釋:  183  假設cap=8(即cap一開始就是2的整次冪)若是沒有cap-1處理的話  184  n |= n >>> 1; 1 0 0 0 | 0 1 0 0 = 1 1 0 0 = 12  185  n |= n >>> 2; 1 1 0 0 | 0 0 1 1 = 1 1 1 1 = 15  186  n |= n >>> 4; 1 1 1 1 | 0 0 0 0 = 1 1 1 1 = 15  187  n |= n >>> 8; 1 1 1 1 | 0 0 0 0 = 1 1 1 1 = 15  188  n |= n >>> 16; 1 1 1 1 | 0 0 0 0 = 1 1 1 1 = 15  189  return n + 1 15 + 1 = 16  190  這樣獲得的容量就不是>=cap的最小2的整次冪值,形成內存空間浪費。  191  若是做cap-1預處理的話就不會這樣。  192  n = cap - 1 = 7 = 0 1 1 1  193  n |= n >>> 1; 0 1 1 1 | 0 0 1 1 = 0 1 1 1 = 7  194  n |= n >>> 2; 0 1 1 1 | 0 0 0 1 = 0 1 1 1 = 7  195  n |= n >>> 4; 0 1 1 1 | 0 0 0 0 = 0 1 1 1 = 7  196  n |= n >>> 8; 0 1 1 1 | 0 0 0 0 = 0 1 1 1 = 7  197  n |= n >>> 16; 0 1 1 1 | 0 0 0 0 = 0 1 1 1 = 7  198  return n + 1 7 + 1 = 8  199     */
 200     static final int tableSizeFor(int cap) {  201         int n = cap - 1;  202         n |= n >>> 1;  203         n |= n >>> 2;  204         n |= n >>> 4;  205         n |= n >>> 8;  206         n |= n >>> 16;  207         return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;  208  }  209     //實際數據的存儲數組
 210     transient Node<K,V>[] table;  211 
 212     transient Set<Map.Entry<K,V>> entrySet;  213 
 214     transient int size;  215 
 216     //fail-fast機制
 217     transient int modCount;  218 
 219     //擴容閾值 threshold=capacity*loadFactor
 220     int threshold;  221 
 222     final float loadFactor;  223     /* ---------------- Public operations -------------- */
 224 
 225     //含參構造函數
 226     public HashMap(int initialCapacity, float loadFactor) {  227         if (initialCapacity < 0)  228             throw new IllegalArgumentException("Illegal initial capacity: " +
 229  initialCapacity);  230         if (initialCapacity > MAXIMUM_CAPACITY)  231             initialCapacity = MAXIMUM_CAPACITY;  232         if (loadFactor <= 0 || Float.isNaN(loadFactor))  233             throw new IllegalArgumentException("Illegal load factor: " +
 234  loadFactor);  235         this.loadFactor = loadFactor;  236         //這裏的閾值並非由threshold=capacity*loadFactor計算獲得的
 237         this.threshold = tableSizeFor(initialCapacity);  238  }  239 
 240     public HashMap(int initialCapacity) {  241         this(initialCapacity, DEFAULT_LOAD_FACTOR);  242  }  243 
 244     public HashMap() {  245         this.loadFactor = DEFAULT_LOAD_FACTOR;  246  }  247 
 248     public HashMap(Map<? extends K, ? extends V> m) {  249         this.loadFactor = DEFAULT_LOAD_FACTOR;  250         putMapEntries(m, false);  251  }  252 
 253     final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {  254         int s = m.size();  255         if (s > 0) {  256             //判斷table是否已經初始化
 257             if (table == null) {  258                 float ft = ((float)s / loadFactor) + 1.0F;  259                 int t = ((ft < (float)MAXIMUM_CAPACITY) ?
 260                          (int)ft : MAXIMUM_CAPACITY);  261                 if (t > threshold)  262                     threshold = tableSizeFor(t);  263  }  264             //已經初始化,且m元素個數>閾值,進行擴容
 265             else if (s > threshold)  266  resize();  267             for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {  268                 K key = e.getKey();  269                 V value = e.getValue();  270                 putVal(hash(key), key, value, false, evict);  271  }  272  }  273  }  274 
 275     public int size() {  276         return size;  277  }  278 
 279     public boolean isEmpty() {  280         return size == 0;  281  }  282     /*
 283  返回key對應的value  284  須要注意的是返回null並不必定表明key不存在,有可能對應的value就是null  285     */
 286     public V get(Object key) {  287         Node<K,V> e;  288         return (e = getNode(hash(key), key)) == null ? null : e.value;  289  }  290     /*
 291  first=tab[(n-1)&hash]是hash對應bin的第一個元素  292  (k=first.key)==key||(key!=null&&key.equals(k))代表HashMap的key能夠爲null  293     */
 294     final Node<K,V> getNode(int hash, Object key) {  295         Node<K,V>[] tab; Node<K,V> first, e; int n; K k;  296         if ((tab = table) != null && (n = tab.length) > 0 &&
 297             (first = tab[(n - 1) & hash]) != null) {  298             //判斷hash對應bin的第一個元素是否爲給定的key
 299             if (first.hash == hash &&
 300                 ((k = first.key) == key || (key != null && key.equals(k))))  301                 return first;  302             //若是hash對應bin有不止一個元素
 303             if ((e = first.next) != null) {  304                 //紅黑樹
 305                 if (first instanceof TreeNode)  306                     return ((TreeNode<K,V>)first).getTreeNode(hash, key);  307                 //鏈表
 308                 do {  309                     if (e.hash == hash &&
 310                         ((k = e.key) == key || (key != null && key.equals(k))))  311                         return e;  312                 } while ((e = e.next) != null);  313  }  314  }  315         return null;  316  }  317     //返回null表明不存在對應的key
 318     public boolean containsKey(Object key) {  319         return getNode(hash(key), key) != null;  320  }  321 
 322     public V put(K key, V value) {  323         return putVal(hash(key), key, value, false, true);  324  }  325 
 326     final V putVal(int hash, K key, V value, boolean onlyIfAbsent,  327                    boolean evict) {  328         Node<K,V>[] tab; Node<K,V> p; int n, i;  329         //判斷數組是否爲null或長度是否爲0,是就擴容
 330         if ((tab = table) == null || (n = tab.length) == 0)  331             n = (tab = resize()).length;  332         //判斷bin第一個元素是否爲null,是就直接插入
 333         if ((p = tab[i = (n - 1) & hash]) == null)  334             tab[i] = newNode(hash, key, value, null);  335         else {  336             Node<K,V> e; K k;  337             //判斷bin第一個元素的key是否和待插入key同樣,是就直接覆蓋
 338             if (p.hash == hash &&
 339                 ((k = p.key) == key || (key != null && key.equals(k))))  340                 e = p;  341             //判斷bin是否爲紅黑樹,是就直接在樹中插入
 342             else if (p instanceof TreeNode)  343                 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);  344             else {  345                 //遍歷
 346                 for (int binCount = 0; ; ++binCount) {  347                     if ((e = p.next) == null) {  348                         p.next = newNode(hash, key, value, null);  349                         if (binCount >= TREEIFY_THRESHOLD - 1)//-1 for 1st
 350  treeifyBin(tab, hash);  351                         break;  352  }  353                     if (e.hash == hash &&
 354                         ((k = e.key) == key || (key != null && key.equals(k))))  355                         break;  356                     p = e;  357  }  358  }  359             if (e != null) {  360                 V oldValue = e.value;  361                 if (!onlyIfAbsent || oldValue == null)  362                     e.value = value;  363  afterNodeAccess(e);  364                 return oldValue;  365  }  366  }  367         ++modCount;  368         if (++size > threshold)  369  resize();  370  afterNodeInsertion(evict);  371         return null;  372  }  373 
 374 
 375     final Node<K,V>[] resize() {  376         //給存儲數組table起別名oldTab
 377         Node<K,V>[] oldTab = table;  378         //獲得擴容前的數組容量和擴容閾值
 379         int oldCap = (oldTab == null) ? 0 : oldTab.length;  380         int oldThr = threshold;  381         //定義新的數組容量和擴容閾值
 382         int newCap, newThr = 0;  383 
 384         if (oldCap > 0) {  385             //到達極限容量,沒法擴容
 386             if (oldCap >= MAXIMUM_CAPACITY) {  387                 /*
 388  直接把擴容閾值置爲Integer.MAX_VALUE即  389  32位hashcode的最大值,以避免再次觸發resize  390                  */
 391                 threshold = Integer.MAX_VALUE;  392                 return oldTab;  393  }  394             //擴容後的新的數組容量爲原來的2倍
 395             else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
 396                      oldCap >= DEFAULT_INITIAL_CAPACITY)  397                 //負載因子不變,新的擴容閾值必定也是原來的2倍
 398                 newThr = oldThr << 1;  399  }  400         else if (oldThr > 0)// initial capacity was placed in threshold
 401             newCap = oldThr;  402         else {              // zero initial threshold signifies using defaults
 403             newCap = DEFAULT_INITIAL_CAPACITY;  404             newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);  405  }  406         if (newThr == 0) {  407             float ft = (float)newCap * loadFactor;  408             newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
 409                       (int)ft : Integer.MAX_VALUE);  410  }  411         threshold = newThr;  412         @SuppressWarnings({"rawtypes","unchecked"})  413             //建立容量爲newCap的newTab
 414             Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];  415         table = newTab;  416         if (oldTab != null) {  417             for (int j = 0; j < oldCap; ++j) {  418                 Node<K,V> e;  419                 if ((e = oldTab[j]) != null) {  420                     oldTab[j] = null;  421                     if (e.next == null)  422                         //e是bucket中惟一的一個元素,則直接賦值到newTab
 423                         newTab[e.hash & (newCap - 1)] = e;  424                     else if (e instanceof TreeNode)  425                         ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);  426                     else {  427                         Node<K,V> loHead = null, loTail = null;  428                         Node<K,V> hiHead = null, hiTail = null;  429                         Node<K,V> next;  430                         do {  431                             next = e.next;  432                             if ((e.hash & oldCap) == 0) {  433                                 if (loTail == null)  434                                     loHead = e;  435                                 else
 436                                     loTail.next = e;  437                                 loTail = e;  438  }  439                             else {  440                                 if (hiTail == null)  441                                     hiHead = e;  442                                 else
 443                                     hiTail.next = e;  444                                 hiTail = e;  445  }  446                         } while ((e = next) != null);  447                         if (loTail != null) {  448                             loTail.next = null;  449                             newTab[j] = loHead;  450  }  451                         if (hiTail != null) {  452                             hiTail.next = null;  453                             newTab[j + oldCap] = hiHead;  454  }  455  }  456  }  457  }  458  }  459         return newTab;  460  }  461 
 462     final void treeifyBin(Node<K,V>[] tab, int hash) {  463         int n, index; Node<K,V> e;  464         if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)  465  resize();  466         else if ((e = tab[index = (n - 1) & hash]) != null) {  467             TreeNode<K,V> hd = null, tl = null;  468             do {  469                 TreeNode<K,V> p = replacementTreeNode(e, null);  470                 if (tl == null)  471                     hd = p;  472                 else {  473                     p.prev = tl;  474                     tl.next = p;  475  }  476                 tl = p;  477             } while ((e = e.next) != null);  478             if ((tab[index] = hd) != null)  479  hd.treeify(tab);  480  }  481  }  482 
 483     public void putAll(Map<? extends K, ? extends V> m) {  484         putMapEntries(m, true);  485  }  486 
 487     public V remove(Object key) {  488         Node<K,V> e;  489         return (e = removeNode(hash(key), key, null, false, true)) == null ?
 490             null : e.value;  491  }  492 
 493     final Node<K,V> removeNode(int hash, Object key, Object value,  494                                boolean matchValue, boolean movable) {  495         Node<K,V>[] tab; Node<K,V> p; int n, index;  496         if ((tab = table) != null && (n = tab.length) > 0 &&
 497             (p = tab[index = (n - 1) & hash]) != null) {  498             Node<K,V> node = null, e; K k; V v;  499             if (p.hash == hash &&
 500                 ((k = p.key) == key || (key != null && key.equals(k))))  501                 node = p;  502             else if ((e = p.next) != null) {  503                 if (p instanceof TreeNode)  504                     node = ((TreeNode<K,V>)p).getTreeNode(hash, key);  505                 else {  506                     do {  507                         if (e.hash == hash &&
 508                             ((k = e.key) == key ||
 509                              (key != null && key.equals(k)))) {  510                             node = e;  511                             break;  512  }  513                         p = e;  514                     } while ((e = e.next) != null);  515  }  516  }  517             if (node != null && (!matchValue || (v = node.value) == value ||
 518                                  (value != null && value.equals(v)))) {  519                 if (node instanceof TreeNode)  520                     ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);  521                 else if (node == p)  522                     tab[index] = node.next;  523                 else
 524                     p.next = node.next;  525                 ++modCount;  526                 --size;  527  afterNodeRemoval(node);  528                 return node;  529  }  530  }  531         return null;  532  }  533 
 534     public void clear() {  535         Node<K,V>[] tab;  536         modCount++;  537         if ((tab = table) != null && size > 0) {  538             size = 0;  539             for (int i = 0; i < tab.length; ++i)  540                 tab[i] = null;  541  }  542  }  543 
 544     public boolean containsValue(Object value) {  545         Node<K,V>[] tab; V v;  546         if ((tab = table) != null && size > 0) {  547             for (int i = 0; i < tab.length; ++i) {  548                 for (Node<K,V> e = tab[i]; e != null; e = e.next) {  549                     if ((v = e.value) == value ||
 550                         (value != null && value.equals(v)))  551                         return true;  552  }  553  }  554  }  555         return false;  556  }  557 
 558     public Set<K> keySet() {  559         Set<K> ks = keySet;  560         if (ks == null) {  561             ks = new KeySet();  562             keySet = ks;  563  }  564         return ks;  565  }  566 
 567     final class KeySet extends AbstractSet<K> {  568         public final int size()                 { return size; }  569         public final void clear()               { HashMap.this.clear(); }  570         public final Iterator<K> iterator()     { return new KeyIterator(); }  571         public final boolean contains(Object o) { return containsKey(o); }  572         public final boolean remove(Object key) {  573             return removeNode(hash(key), key, null, false, true) != null;  574  }  575         public final Spliterator<K> spliterator() {  576             return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);  577  }  578         public final void forEach(Consumer<? super K> action) {  579             Node<K,V>[] tab;  580             if (action == null)  581                 throw new NullPointerException();  582             if (size > 0 && (tab = table) != null) {  583                 int mc = modCount;  584                 for (int i = 0; i < tab.length; ++i) {  585                     for (Node<K,V> e = tab[i]; e != null; e = e.next)  586  action.accept(e.key);  587  }  588                 if (modCount != mc)  589                     throw new ConcurrentModificationException();  590  }  591  }  592  }  593 
 594     public Collection<V> values() {  595         Collection<V> vs = values;  596         if (vs == null) {  597             vs = new Values();  598             values = vs;  599  }  600         return vs;  601  }  602 
 603     final class Values extends AbstractCollection<V> {  604         public final int size()                 { return size; }  605         public final void clear()               { HashMap.this.clear(); }  606         public final Iterator<V> iterator()     { return new ValueIterator(); }  607         public final boolean contains(Object o) { return containsValue(o); }  608         public final Spliterator<V> spliterator() {  609             return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);  610  }  611         public final void forEach(Consumer<? super V> action) {  612             Node<K,V>[] tab;  613             if (action == null)  614                 throw new NullPointerException();  615             if (size > 0 && (tab = table) != null) {  616                 int mc = modCount;  617                 for (int i = 0; i < tab.length; ++i) {  618                     for (Node<K,V> e = tab[i]; e != null; e = e.next)  619  action.accept(e.value);  620  }  621                 if (modCount != mc)  622                     throw new ConcurrentModificationException();  623  }  624  }  625  }  626 
 627     public Set<Map.Entry<K,V>> entrySet() {  628         Set<Map.Entry<K,V>> es;  629         return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;  630  }  631 
 632     final class EntrySet extends AbstractSet<Map.Entry<K,V>> {  633         public final int size()                 { return size; }  634         public final void clear()               { HashMap.this.clear(); }  635         public final Iterator<Map.Entry<K,V>> iterator() {  636             return new EntryIterator();  637  }  638         public final boolean contains(Object o) {  639             if (!(o instanceof Map.Entry))  640                 return false;  641             Map.Entry<?,?> e = (Map.Entry<?,?>) o;  642             Object key = e.getKey();  643             Node<K,V> candidate = getNode(hash(key), key);  644             return candidate != null && candidate.equals(e);  645  }  646         public final boolean remove(Object o) {  647             if (o instanceof Map.Entry) {  648                 Map.Entry<?,?> e = (Map.Entry<?,?>) o;  649                 Object key = e.getKey();  650                 Object value = e.getValue();  651                 return removeNode(hash(key), key, value, true, true) != null;  652  }  653             return false;  654  }  655         public final Spliterator<Map.Entry<K,V>> spliterator() {  656             return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);  657  }  658         public final void forEach(Consumer<? super Map.Entry<K,V>> action) {  659             Node<K,V>[] tab;  660             if (action == null)  661                 throw new NullPointerException();  662             if (size > 0 && (tab = table) != null) {  663                 int mc = modCount;  664                 for (int i = 0; i < tab.length; ++i) {  665                     for (Node<K,V> e = tab[i]; e != null; e = e.next)  666  action.accept(e);  667  }  668                 if (modCount != mc)  669                     throw new ConcurrentModificationException();  670  }  671  }  672  }  673 
 674  @Override  675     public V getOrDefault(Object key, V defaultValue) {  676         Node<K,V> e;  677         return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;  678  }  679 
 680  @Override  681     public V putIfAbsent(K key, V value) {  682         return putVal(hash(key), key, value, true, true);  683  }  684 
 685  @Override  686     public boolean remove(Object key, Object value) {  687         return removeNode(hash(key), key, value, true, true) != null;  688  }  689 
 690  @Override  691     public boolean replace(K key, V oldValue, V newValue) {  692         Node<K,V> e; V v;  693         if ((e = getNode(hash(key), key)) != null &&
 694             ((v = e.value) == oldValue || (v != null && v.equals(oldValue)))) {  695             e.value = newValue;  696  afterNodeAccess(e);  697             return true;  698  }  699         return false;  700  }  701 
 702  @Override  703     public V replace(K key, V value) {  704         Node<K,V> e;  705         if ((e = getNode(hash(key), key)) != null) {  706             V oldValue = e.value;  707             e.value = value;  708  afterNodeAccess(e);  709             return oldValue;  710  }  711         return null;  712  }  713 
 714  @Override  715     public V computeIfAbsent(K key,  716                              Function<? super K, ? extends V> mappingFunction) {  717         if (mappingFunction == null)  718             throw new NullPointerException();  719         int hash = hash(key);  720         Node<K,V>[] tab; Node<K,V> first; int n, i;  721         int binCount = 0;  722         TreeNode<K,V> t = null;  723         Node<K,V> old = null;  724         if (size > threshold || (tab = table) == null ||
 725             (n = tab.length) == 0)  726             n = (tab = resize()).length;  727         if ((first = tab[i = (n - 1) & hash]) != null) {  728             if (first instanceof TreeNode)  729                 old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);  730             else {  731                 Node<K,V> e = first; K k;  732                 do {  733                     if (e.hash == hash &&
 734                         ((k = e.key) == key || (key != null && key.equals(k)))) {  735                         old = e;  736                         break;  737  }  738                     ++binCount;  739                 } while ((e = e.next) != null);  740  }  741  V oldValue;  742             if (old != null && (oldValue = old.value) != null) {  743  afterNodeAccess(old);  744                 return oldValue;  745  }  746  }  747         V v = mappingFunction.apply(key);  748         if (v == null) {  749             return null;  750         } else if (old != null) {  751             old.value = v;  752  afterNodeAccess(old);  753             return v;  754  }  755         else if (t != null)  756             t.putTreeVal(this, tab, hash, key, v);  757         else {  758             tab[i] = newNode(hash, key, v, first);  759             if (binCount >= TREEIFY_THRESHOLD - 1)  760  treeifyBin(tab, hash);  761  }  762         ++modCount;  763         ++size;  764         afterNodeInsertion(true);  765         return v;  766  }  767 
 768     public V computeIfPresent(K key,  769                               BiFunction<? super K, ? super V, ? extends V> remappingFunction) {  770         if (remappingFunction == null)  771             throw new NullPointerException();  772         Node<K,V> e; V oldValue;  773         int hash = hash(key);  774         if ((e = getNode(hash, key)) != null &&
 775             (oldValue = e.value) != null) {  776             V v = remappingFunction.apply(key, oldValue);  777             if (v != null) {  778                 e.value = v;  779  afterNodeAccess(e);  780                 return v;  781  }  782             else
 783                 removeNode(hash, key, null, false, true);  784  }  785         return null;  786  }  787 
 788  @Override  789     public V compute(K key,  790                      BiFunction<? super K, ? super V, ? extends V> remappingFunction) {  791         if (remappingFunction == null)  792             throw new NullPointerException();  793         int hash = hash(key);  794         Node<K,V>[] tab; Node<K,V> first; int n, i;  795         int binCount = 0;  796         TreeNode<K,V> t = null;  797         Node<K,V> old = null;  798         if (size > threshold || (tab = table) == null ||
 799             (n = tab.length) == 0)  800             n = (tab = resize()).length;  801         if ((first = tab[i = (n - 1) & hash]) != null) {  802             if (first instanceof TreeNode)  803                 old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);  804             else {  805                 Node<K,V> e = first; K k;  806                 do {  807                     if (e.hash == hash &&
 808                         ((k = e.key) == key || (key != null && key.equals(k)))) {  809                         old = e;  810                         break;  811  }  812                     ++binCount;  813                 } while ((e = e.next) != null);  814  }  815  }  816         V oldValue = (old == null) ? null : old.value;  817         V v = remappingFunction.apply(key, oldValue);  818         if (old != null) {  819             if (v != null) {  820                 old.value = v;  821  afterNodeAccess(old);  822  }  823             else
 824                 removeNode(hash, key, null, false, true);  825  }  826         else if (v != null) {  827             if (t != null)  828                 t.putTreeVal(this, tab, hash, key, v);  829             else {  830                 tab[i] = newNode(hash, key, v, first);  831                 if (binCount >= TREEIFY_THRESHOLD - 1)  832  treeifyBin(tab, hash);  833  }  834             ++modCount;  835             ++size;  836             afterNodeInsertion(true);  837  }  838         return v;  839  }  840 
 841  @Override  842     public V merge(K key, V value,  843                    BiFunction<? super V, ? super V, ? extends V> remappingFunction) {  844         if (value == null)  845             throw new NullPointerException();  846         if (remappingFunction == null)  847             throw new NullPointerException();  848         int hash = hash(key);  849         Node<K,V>[] tab; Node<K,V> first; int n, i;  850         int binCount = 0;  851         TreeNode<K,V> t = null;  852         Node<K,V> old = null;  853         if (size > threshold || (tab = table) == null ||
 854             (n = tab.length) == 0)  855             n = (tab = resize()).length;  856         if ((first = tab[i = (n - 1) & hash]) != null) {  857             if (first instanceof TreeNode)  858                 old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key);  859             else {  860                 Node<K,V> e = first; K k;  861                 do {  862                     if (e.hash == hash &&
 863                         ((k = e.key) == key || (key != null && key.equals(k)))) {  864                         old = e;  865                         break;  866  }  867                     ++binCount;  868                 } while ((e = e.next) != null);  869  }  870  }  871         if (old != null) {  872  V v;  873             if (old.value != null)  874                 v = remappingFunction.apply(old.value, value);  875             else
 876                 v = value;  877             if (v != null) {  878                 old.value = v;  879  afterNodeAccess(old);  880  }  881             else
 882                 removeNode(hash, key, null, false, true);  883             return v;  884  }  885         if (value != null) {  886             if (t != null)  887                 t.putTreeVal(this, tab, hash, key, value);  888             else {  889                 tab[i] = newNode(hash, key, value, first);  890                 if (binCount >= TREEIFY_THRESHOLD - 1)  891  treeifyBin(tab, hash);  892  }  893             ++modCount;  894             ++size;  895             afterNodeInsertion(true);  896  }  897         return value;  898  }  899 
 900  @Override  901     public void forEach(BiConsumer<? super K, ? super V> action) {  902         Node<K,V>[] tab;  903         if (action == null)  904             throw new NullPointerException();  905         if (size > 0 && (tab = table) != null) {  906             int mc = modCount;  907             for (int i = 0; i < tab.length; ++i) {  908                 for (Node<K,V> e = tab[i]; e != null; e = e.next)  909  action.accept(e.key, e.value);  910  }  911             if (modCount != mc)  912                 throw new ConcurrentModificationException();  913  }  914  }  915 
 916  @Override  917     public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {  918         Node<K,V>[] tab;  919         if (function == null)  920             throw new NullPointerException();  921         if (size > 0 && (tab = table) != null) {  922             int mc = modCount;  923             for (int i = 0; i < tab.length; ++i) {  924                 for (Node<K,V> e = tab[i]; e != null; e = e.next) {  925                     e.value = function.apply(e.key, e.value);  926  }  927  }  928             if (modCount != mc)  929                 throw new ConcurrentModificationException();  930  }  931  }  932     /* ---------------- Cloning and serialization -------------- */
 933 
 934     @SuppressWarnings("unchecked")  935  @Override  936     public Object clone() {  937         HashMap<K,V> result;  938         try {  939             result = (HashMap<K,V>)super.clone();  940         } catch (CloneNotSupportedException e) {  941             throw new InternalError(e);  942  }  943  result.reinitialize();  944         result.putMapEntries(this, false);  945         return result;  946  }  947 
 948     final float loadFactor() { return loadFactor; }  949     final int capacity() {  950         return (table != null) ? table.length :  951             (threshold > 0) ? threshold :  952  DEFAULT_INITIAL_CAPACITY;  953  }  954 
 955     private void writeObject(java.io.ObjectOutputStream s)  956         throws IOException {  957         int buckets = capacity();  958  s.defaultWriteObject();  959  s.writeInt(buckets);  960  s.writeInt(size);  961  internalWriteEntries(s);  962  }  963 
 964     private void readObject(java.io.ObjectInputStream s)  965         throws IOException, ClassNotFoundException {  966  s.defaultReadObject();  967  reinitialize();  968         if (loadFactor <= 0 || Float.isNaN(loadFactor))  969             throw new InvalidObjectException("Illegal load factor: " +
 970  loadFactor);  971  s.readInt();  972         int mappings = s.readInt();  973         if (mappings < 0)  974             throw new InvalidObjectException("Illegal mappings count: " +
 975  mappings);  976         else if (mappings > 0) {  977             float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);  978             float fc = (float)mappings / lf + 1.0f;  979             int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
 980  DEFAULT_INITIAL_CAPACITY :  981                        (fc >= MAXIMUM_CAPACITY) ?
 982  MAXIMUM_CAPACITY :  983                        tableSizeFor((int)fc));  984             float ft = (float)cap * lf;  985             threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
 986                          (int)ft : Integer.MAX_VALUE);  987             @SuppressWarnings({"rawtypes","unchecked"})  988                 Node<K,V>[] tab = (Node<K,V>[])new Node[cap];  989             table = tab;  990 
 991             for (int i = 0; i < mappings; i++) {  992                 @SuppressWarnings("unchecked")  993                     K key = (K) s.readObject();  994                 @SuppressWarnings("unchecked")  995                     V value = (V) s.readObject();  996                 putVal(hash(key), key, value, false, false);  997  }  998  }  999  } 1000 
1001     /* ---------------- iterators -------------- */
1002 
1003     abstract class HashIterator { 1004         Node<K,V> next; 1005         Node<K,V> current; 1006         int expectedModCount; 1007         int index; 1008 
1009  HashIterator() { 1010             expectedModCount = modCount; 1011             Node<K,V>[] t = table; 1012             current = next = null; 1013             index = 0; 1014             if (t != null && size > 0) { 1015                 do {} while (index < t.length && (next = t[index++]) == null); 1016  } 1017  } 1018 
1019         public final boolean hasNext() { 1020             return next != null; 1021  } 1022 
1023         final Node<K,V> nextNode() { 1024             Node<K,V>[] t; 1025             Node<K,V> e = next; 1026             if (modCount != expectedModCount) 1027                 throw new ConcurrentModificationException(); 1028             if (e == null) 1029                 throw new NoSuchElementException(); 1030             if ((next = (current = e).next) == null && (t = table) != null) { 1031                 do {} while (index < t.length && (next = t[index++]) == null); 1032  } 1033             return e; 1034  } 1035 
1036         public final void remove() { 1037             Node<K,V> p = current; 1038             if (p == null) 1039                 throw new IllegalStateException(); 1040             if (modCount != expectedModCount) 1041                 throw new ConcurrentModificationException(); 1042             current = null; 1043             K key = p.key; 1044             removeNode(hash(key), key, null, false, false); 1045             expectedModCount = modCount; 1046  } 1047  } 1048 
1049     final class KeyIterator extends HashIterator 1050         implements Iterator<K> { 1051         public final K next() { return nextNode().key; } 1052  } 1053 
1054     final class ValueIterator extends HashIterator 1055         implements Iterator<V> { 1056         public final V next() { return nextNode().value; } 1057  } 1058 
1059     final class EntryIterator extends HashIterator 1060         implements Iterator<Map.Entry<K,V>> { 1061         public final Map.Entry<K,V> next() { return nextNode(); } 1062  } 1063 
1064     /* ---------------- spliterators -------------- */
1065 
1066     static class HashMapSpliterator<K,V> { 1067         final HashMap<K,V> map; 1068         Node<K,V> current; 1069         int index; 1070         int fence; 1071         int est; 1072         int expectedModCount; 1073 
1074         HashMapSpliterator(HashMap<K,V> m, int origin, 1075                            int fence, int est, 1076                            int expectedModCount) { 1077             this.map = m; 1078             this.index = origin; 1079             this.fence = fence; 1080             this.est = est; 1081             this.expectedModCount = expectedModCount; 1082  } 1083 
1084         final int getFence() { 1085             int hi; 1086             if ((hi = fence) < 0) { 1087                 HashMap<K,V> m = map; 1088                 est = m.size; 1089                 expectedModCount = m.modCount; 1090                 Node<K,V>[] tab = m.table; 1091                 hi = fence = (tab == null) ? 0 : tab.length; 1092  } 1093             return hi; 1094  } 1095 
1096         public final long estimateSize() { 1097  getFence(); 1098             return (long) est; 1099  } 1100  } 1101 
1102     static final class KeySpliterator<K,V>
1103         extends HashMapSpliterator<K,V>
1104         implements Spliterator<K> { 1105         KeySpliterator(HashMap<K,V> m, int origin, int fence, int est, 1106                        int expectedModCount) { 1107             super(m, origin, fence, est, expectedModCount); 1108  } 1109 
1110         public KeySpliterator<K,V> trySplit() { 1111             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; 1112             return (lo >= mid || current != null) ? null : 1113                 new KeySpliterator<>(map, lo, index = mid, est >>>= 1, 1114  expectedModCount); 1115  } 1116 
1117         public void forEachRemaining(Consumer<? super K> action) { 1118             int i, hi, mc; 1119             if (action == null) 1120                 throw new NullPointerException(); 1121             HashMap<K,V> m = map; 1122             Node<K,V>[] tab = m.table; 1123             if ((hi = fence) < 0) { 1124                 mc = expectedModCount = m.modCount; 1125                 hi = fence = (tab == null) ? 0 : tab.length; 1126  } 1127             else
1128                 mc = expectedModCount; 1129             if (tab != null && tab.length >= hi &&
1130                 (i = index) >= 0 && (i < (index = hi) || current != null)) { 1131                 Node<K,V> p = current; 1132                 current = null; 1133                 do { 1134                     if (p == null) 1135                         p = tab[i++]; 1136                     else { 1137  action.accept(p.key); 1138                         p = p.next; 1139  } 1140                 } while (p != null || i < hi); 1141                 if (m.modCount != mc) 1142                     throw new ConcurrentModificationException(); 1143  } 1144  } 1145 
1146         public boolean tryAdvance(Consumer<? super K> action) { 1147             int hi; 1148             if (action == null) 1149                 throw new NullPointerException(); 1150             Node<K,V>[] tab = map.table; 1151             if (tab != null && tab.length >= (hi = getFence()) && index >= 0) { 1152                 while (current != null || index < hi) { 1153                     if (current == null) 1154                         current = tab[index++]; 1155                     else { 1156                         K k = current.key; 1157                         current = current.next; 1158  action.accept(k); 1159                         if (map.modCount != expectedModCount) 1160                             throw new ConcurrentModificationException(); 1161                         return true; 1162  } 1163  } 1164  } 1165             return false; 1166  } 1167 
1168         public int characteristics() { 1169             return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
1170  Spliterator.DISTINCT; 1171  } 1172  } 1173 
1174     static final class ValueSpliterator<K,V>
1175         extends HashMapSpliterator<K,V>
1176         implements Spliterator<V> { 1177         ValueSpliterator(HashMap<K,V> m, int origin, int fence, int est, 1178                          int expectedModCount) { 1179             super(m, origin, fence, est, expectedModCount); 1180  } 1181 
1182         public ValueSpliterator<K,V> trySplit() { 1183             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; 1184             return (lo >= mid || current != null) ? null : 1185                 new ValueSpliterator<>(map, lo, index = mid, est >>>= 1, 1186  expectedModCount); 1187  } 1188 
1189         public void forEachRemaining(Consumer<? super V> action) { 1190             int i, hi, mc; 1191             if (action == null) 1192                 throw new NullPointerException(); 1193             HashMap<K,V> m = map; 1194             Node<K,V>[] tab = m.table; 1195             if ((hi = fence) < 0) { 1196                 mc = expectedModCount = m.modCount; 1197                 hi = fence = (tab == null) ? 0 : tab.length; 1198  } 1199             else
1200                 mc = expectedModCount; 1201             if (tab != null && tab.length >= hi &&
1202                 (i = index) >= 0 && (i < (index = hi) || current != null)) { 1203                 Node<K,V> p = current; 1204                 current = null; 1205                 do { 1206                     if (p == null) 1207                         p = tab[i++]; 1208                     else { 1209  action.accept(p.value); 1210                         p = p.next; 1211  } 1212                 } while (p != null || i < hi); 1213                 if (m.modCount != mc) 1214                     throw new ConcurrentModificationException(); 1215  } 1216  } 1217 
1218         public boolean tryAdvance(Consumer<? super V> action) { 1219             int hi; 1220             if (action == null) 1221                 throw new NullPointerException(); 1222             Node<K,V>[] tab = map.table; 1223             if (tab != null && tab.length >= (hi = getFence()) && index >= 0) { 1224                 while (current != null || index < hi) { 1225                     if (current == null) 1226                         current = tab[index++]; 1227                     else { 1228                         V v = current.value; 1229                         current = current.next; 1230  action.accept(v); 1231                         if (map.modCount != expectedModCount) 1232                             throw new ConcurrentModificationException(); 1233                         return true; 1234  } 1235  } 1236  } 1237             return false; 1238  } 1239 
1240         public int characteristics() { 1241             return (fence < 0 || est == map.size ? Spliterator.SIZED : 0); 1242  } 1243  } 1244 
1245     static final class EntrySpliterator<K,V>
1246         extends HashMapSpliterator<K,V>
1247         implements Spliterator<Map.Entry<K,V>> { 1248         EntrySpliterator(HashMap<K,V> m, int origin, int fence, int est, 1249                          int expectedModCount) { 1250             super(m, origin, fence, est, expectedModCount); 1251  } 1252 
1253         public EntrySpliterator<K,V> trySplit() { 1254             int hi = getFence(), lo = index, mid = (lo + hi) >>> 1; 1255             return (lo >= mid || current != null) ? null : 1256                 new EntrySpliterator<>(map, lo, index = mid, est >>>= 1, 1257  expectedModCount); 1258  } 1259 
1260         public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) { 1261             int i, hi, mc; 1262             if (action == null) 1263                 throw new NullPointerException(); 1264             HashMap<K,V> m = map; 1265             Node<K,V>[] tab = m.table; 1266             if ((hi = fence) < 0) { 1267                 mc = expectedModCount = m.modCount; 1268                 hi = fence = (tab == null) ? 0 : tab.length; 1269  } 1270             else
1271                 mc = expectedModCount; 1272             if (tab != null && tab.length >= hi &&
1273                 (i = index) >= 0 && (i < (index = hi) || current != null)) { 1274                 Node<K,V> p = current; 1275                 current = null; 1276                 do { 1277                     if (p == null) 1278                         p = tab[i++]; 1279                     else { 1280  action.accept(p); 1281                         p = p.next; 1282  } 1283                 } while (p != null || i < hi); 1284                 if (m.modCount != mc) 1285                     throw new ConcurrentModificationException(); 1286  } 1287  } 1288 
1289         public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) { 1290             int hi; 1291             if (action == null) 1292                 throw new NullPointerException(); 1293             Node<K,V>[] tab = map.table; 1294             if (tab != null && tab.length >= (hi = getFence()) && index >= 0) { 1295                 while (current != null || index < hi) { 1296                     if (current == null) 1297                         current = tab[index++]; 1298                     else { 1299                         Node<K,V> e = current; 1300                         current = current.next; 1301  action.accept(e); 1302                         if (map.modCount != expectedModCount) 1303                             throw new ConcurrentModificationException(); 1304                         return true; 1305  } 1306  } 1307  } 1308             return false; 1309  } 1310 
1311         public int characteristics() { 1312             return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
1313  Spliterator.DISTINCT; 1314  } 1315  } 1316 
1317     /* ---------------- LinkedHashMap support -------------- */
1318 
1319     Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) { 1320         return new Node<>(hash, key, value, next); 1321  } 1322 
1323     Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) { 1324         return new Node<>(p.hash, p.key, p.value, next); 1325  } 1326 
1327     TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) { 1328         return new TreeNode<>(hash, key, value, next); 1329  } 1330 
1331     TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) { 1332         return new TreeNode<>(p.hash, p.key, p.value, next); 1333  } 1334 
1335     void reinitialize() { 1336         table = null; 1337         entrySet = null; 1338         keySet = null; 1339         values = null; 1340         modCount = 0; 1341         threshold = 0; 1342         size = 0; 1343  } 1344 
1345     void afterNodeAccess(Node<K,V> p) { } 1346     void afterNodeInsertion(boolean evict) { } 1347     void afterNodeRemoval(Node<K,V> p) { } 1348 
1349     void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException { 1350         Node<K,V>[] tab; 1351         if (size > 0 && (tab = table) != null) { 1352             for (int i = 0; i < tab.length; ++i) { 1353                 for (Node<K,V> e = tab[i]; e != null; e = e.next) { 1354  s.writeObject(e.key); 1355  s.writeObject(e.value); 1356  } 1357  } 1358  } 1359  } 1360 
1361     /* ---------------- Tree bins -------------- */
1362 
1363     static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> { 1364         TreeNode<K,V> parent; 1365         TreeNode<K,V> left; 1366         TreeNode<K,V> right; 1367         TreeNode<K,V> prev; 1368         boolean red; 1369         TreeNode(int hash, K key, V val, Node<K,V> next) { 1370             super(hash, key, val, next); 1371  } 1372 
1373         final TreeNode<K,V> root() { 1374             for (TreeNode<K,V> r = this, p;;) { 1375                 if ((p = r.parent) == null) 1376                     return r; 1377                 r = p; 1378  } 1379  } 1380 
1381         static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) { 1382             int n; 1383             if (root != null && tab != null && (n = tab.length) > 0) { 1384                 int index = (n - 1) & root.hash; 1385                 TreeNode<K,V> first = (TreeNode<K,V>)tab[index]; 1386                 if (root != first) { 1387                     Node<K,V> rn; 1388                     tab[index] = root; 1389                     TreeNode<K,V> rp = root.prev; 1390                     if ((rn = root.next) != null) 1391                         ((TreeNode<K,V>)rn).prev = rp; 1392                     if (rp != null) 1393                         rp.next = rn; 1394                     if (first != null) 1395                         first.prev = root; 1396                     root.next = first; 1397                     root.prev = null; 1398  } 1399                 assert checkInvariants(root); 1400  } 1401  } 1402 
1403         final TreeNode<K,V> find(int h, Object k, Class<?> kc) { 1404             TreeNode<K,V> p = this; 1405             do { 1406                 int ph, dir; K pk; 1407                 TreeNode<K,V> pl = p.left, pr = p.right, q; 1408                 if ((ph = p.hash) > h) 1409                     p = pl; 1410                 else if (ph < h) 1411                     p = pr; 1412                 else if ((pk = p.key) == k || (k != null && k.equals(pk))) 1413                     return p; 1414                 else if (pl == null) 1415                     p = pr; 1416                 else if (pr == null) 1417                     p = pl; 1418                 else if ((kc != null ||
1419                           (kc = comparableClassFor(k)) != null) &&
1420                          (dir = compareComparables(kc, k, pk)) != 0) 1421                     p = (dir < 0) ? pl : pr; 1422                 else if ((q = pr.find(h, k, kc)) != null) 1423                     return q; 1424                 else
1425                     p = pl; 1426             } while (p != null); 1427             return null; 1428  } 1429 
1430         final TreeNode<K,V> getTreeNode(int h, Object k) { 1431             return ((parent != null) ? root() : this).find(h, k, null); 1432  } 1433 
1434         static int tieBreakOrder(Object a, Object b) { 1435             int d; 1436             if (a == null || b == null ||
1437                 (d = a.getClass().getName(). 1438                  compareTo(b.getClass().getName())) == 0) 1439                 d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
1440                      -1 : 1); 1441             return d; 1442  } 1443 
1444         final void treeify(Node<K,V>[] tab) { 1445             TreeNode<K,V> root = null; 1446             for (TreeNode<K,V> x = this, next; x != null; x = next) { 1447                 next = (TreeNode<K,V>)x.next; 1448                 x.left = x.right = null; 1449                 if (root == null) { 1450                     x.parent = null; 1451                     x.red = false; 1452                     root = x; 1453  } 1454                 else { 1455                     K k = x.key; 1456                     int h = x.hash; 1457                     Class<?> kc = null; 1458                     for (TreeNode<K,V> p = root;;) { 1459                         int dir, ph; 1460                         K pk = p.key; 1461                         if ((ph = p.hash) > h) 1462                             dir = -1; 1463                         else if (ph < h) 1464                             dir = 1; 1465                         else if ((kc == null &&
1466                                   (kc = comparableClassFor(k)) == null) ||
1467                                  (dir = compareComparables(kc, k, pk)) == 0) 1468                             dir = tieBreakOrder(k, pk); 1469 
1470                         TreeNode<K,V> xp = p; 1471                         if ((p = (dir <= 0) ? p.left : p.right) == null) { 1472                             x.parent = xp; 1473                             if (dir <= 0) 1474                                 xp.left = x; 1475                             else
1476                                 xp.right = x; 1477                             root = balanceInsertion(root, x); 1478                             break; 1479  } 1480  } 1481  } 1482  } 1483  moveRootToFront(tab, root); 1484  } 1485 
1486         final Node<K,V> untreeify(HashMap<K,V> map) { 1487             Node<K,V> hd = null, tl = null; 1488             for (Node<K,V> q = this; q != null; q = q.next) { 1489                 Node<K,V> p = map.replacementNode(q, null); 1490                 if (tl == null) 1491                     hd = p; 1492                 else
1493                     tl.next = p; 1494                 tl = p; 1495  } 1496             return hd; 1497  } 1498 
1499         final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab, 1500                                        int h, K k, V v) { 1501             Class<?> kc = null; 1502             boolean searched = false; 1503             TreeNode<K,V> root = (parent != null) ? root() : this; 1504             for (TreeNode<K,V> p = root;;) { 1505                 int dir, ph; K pk; 1506                 if ((ph = p.hash) > h) 1507                     dir = -1; 1508                 else if (ph < h) 1509                     dir = 1; 1510                 else if ((pk = p.key) == k || (k != null && k.equals(pk))) 1511                     return p; 1512                 else if ((kc == null &&
1513                           (kc = comparableClassFor(k)) == null) ||
1514                          (dir = compareComparables(kc, k, pk)) == 0) { 1515                     if (!searched) { 1516                         TreeNode<K,V> q, ch; 1517                         searched = true; 1518                         if (((ch = p.left) != null &&
1519                              (q = ch.find(h, k, kc)) != null) ||
1520                             ((ch = p.right) != null &&
1521                              (q = ch.find(h, k, kc)) != null)) 1522                             return q; 1523  } 1524                     dir = tieBreakOrder(k, pk); 1525  } 1526 
1527                 TreeNode<K,V> xp = p; 1528                 if ((p = (dir <= 0) ? p.left : p.right) == null) { 1529                     Node<K,V> xpn = xp.next; 1530                     TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn); 1531                     if (dir <= 0) 1532                         xp.left = x; 1533                     else
1534                         xp.right = x; 1535                     xp.next = x; 1536                     x.parent = x.prev = xp; 1537                     if (xpn != null) 1538                         ((TreeNode<K,V>)xpn).prev = x; 1539  moveRootToFront(tab, balanceInsertion(root, x)); 1540                     return null; 1541  } 1542  } 1543  } 1544 
1545         final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab, 1546                                   boolean movable) { 1547             int n; 1548             if (tab == null || (n = tab.length) == 0) 1549                 return; 1550             int index = (n - 1) & hash; 1551             TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl; 1552             TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev; 1553             if (pred == null) 1554                 tab[index] = first = succ; 1555             else
1556                 pred.next = succ; 1557             if (succ != null) 1558                 succ.prev = pred; 1559             if (first == null) 1560                 return; 1561             if (root.parent != null) 1562                 root = root.root(); 1563             if (root == null || root.right == null ||
1564                 (rl = root.left) == null || rl.left == null) { 1565                 tab[index] = first.untreeify(map); 1566                 return; 1567  } 1568             TreeNode<K,V> p = this, pl = left, pr = right, replacement; 1569             if (pl != null && pr != null) { 1570                 TreeNode<K,V> s = pr, sl; 1571                 while ((sl = s.left) != null) 1572                     s = sl; 1573                 boolean c = s.red; s.red = p.red; p.red = c; 1574                 TreeNode<K,V> sr = s.right; 1575                 TreeNode<K,V> pp = p.parent; 1576                 if (s == pr) { 1577                     p.parent = s; 1578                     s.right = p; 1579  } 1580                 else { 1581                     TreeNode<K,V> sp = s.parent; 1582                     if ((p.parent = sp) != null) { 1583                         if (s == sp.left) 1584                             sp.left = p; 1585                         else
1586                             sp.right = p; 1587  } 1588                     if ((s.right = pr) != null) 1589                         pr.parent = s; 1590  } 1591                 p.left = null; 1592                 if ((p.right = sr) != null) 1593                     sr.parent = p; 1594                 if ((s.left = pl) != null) 1595                     pl.parent = s; 1596                 if ((s.parent = pp) == null) 1597                     root = s; 1598                 else if (p == pp.left) 1599                     pp.left = s; 1600                 else
1601                     pp.right = s; 1602                 if (sr != null) 1603                     replacement = sr; 1604                 else
1605                     replacement = p; 1606  } 1607             else if (pl != null) 1608                 replacement = pl; 1609             else if (pr != null) 1610                 replacement = pr; 1611             else
1612                 replacement = p; 1613             if (replacement != p) { 1614                 TreeNode<K,V> pp = replacement.parent = p.parent; 1615                 if (pp == null) 1616                     root = replacement; 1617                 else if (p == pp.left) 1618                     pp.left = replacement; 1619                 else
1620                     pp.right = replacement; 1621                 p.left = p.right = p.parent = null; 1622  } 1623 
1624             TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement); 1625 
1626             if (replacement == p) { 1627                 TreeNode<K,V> pp = p.parent; 1628                 p.parent = null; 1629                 if (pp != null) { 1630                     if (p == pp.left) 1631                         pp.left = null; 1632                     else if (p == pp.right) 1633                         pp.right = null; 1634  } 1635  } 1636             if (movable) 1637  moveRootToFront(tab, r); 1638  } 1639 
1640         final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) { 1641             TreeNode<K,V> b = this; 1642             TreeNode<K,V> loHead = null, loTail = null; 1643             TreeNode<K,V> hiHead = null, hiTail = null; 1644             int lc = 0, hc = 0; 1645             for (TreeNode<K,V> e = b, next; e != null; e = next) { 1646                 next = (TreeNode<K,V>)e.next; 1647                 e.next = null; 1648                 if ((e.hash & bit) == 0) { 1649                     if ((e.prev = loTail) == null) 1650                         loHead = e; 1651                     else
1652                         loTail.next = e; 1653                     loTail = e; 1654                     ++lc; 1655  } 1656                 else { 1657                     if ((e.prev = hiTail) == null) 1658                         hiHead = e; 1659                     else
1660                         hiTail.next = e; 1661                     hiTail = e; 1662                     ++hc; 1663  } 1664  } 1665 
1666             if (loHead != null) { 1667                 if (lc <= UNTREEIFY_THRESHOLD) 1668                     tab[index] = loHead.untreeify(map); 1669                 else { 1670                     tab[index] = loHead; 1671                     if (hiHead != null) 1672  loHead.treeify(tab); 1673  } 1674  } 1675             if (hiHead != null) { 1676                 if (hc <= UNTREEIFY_THRESHOLD) 1677                     tab[index + bit] = hiHead.untreeify(map); 1678                 else { 1679                     tab[index + bit] = hiHead; 1680                     if (loHead != null) 1681  hiHead.treeify(tab); 1682  } 1683  } 1684  } 1685 
1686         /* ---------------- Red-black tree methods, all adapted from CLR -------------- */
1687 
1688         static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root, 1689                                               TreeNode<K,V> p) { 1690             TreeNode<K,V> r, pp, rl; 1691             if (p != null && (r = p.right) != null) { 1692                 if ((rl = p.right = r.left) != null) 1693                     rl.parent = p; 1694                 if ((pp = r.parent = p.parent) == null) 1695                     (root = r).red = false; 1696                 else if (pp.left == p) 1697                     pp.left = r; 1698                 else
1699                     pp.right = r; 1700                 r.left = p; 1701                 p.parent = r; 1702  } 1703             return root; 1704  } 1705 
1706         static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root, 1707                                                TreeNode<K,V> p) { 1708             TreeNode<K,V> l, pp, lr; 1709             if (p != null && (l = p.left) != null) { 1710                 if ((lr = p.left = l.right) != null) 1711                     lr.parent = p; 1712                 if ((pp = l.parent = p.parent) == null) 1713                     (root = l).red = false; 1714                 else if (pp.right == p) 1715                     pp.right = l; 1716                 else
1717                     pp.left = l; 1718                 l.right = p; 1719                 p.parent = l; 1720  } 1721             return root; 1722  } 1723 
1724         static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root, 1725                                                     TreeNode<K,V> x) { 1726             x.red = true; 1727             for (TreeNode<K,V> xp, xpp, xppl, xppr;;) { 1728                 if ((xp = x.parent) == null) { 1729                     x.red = false; 1730                     return x; 1731  } 1732                 else if (!xp.red || (xpp = xp.parent) == null) 1733                     return root; 1734                 if (xp == (xppl = xpp.left)) { 1735                     if ((xppr = xpp.right) != null && xppr.red) { 1736                         xppr.red = false; 1737                         xp.red = false; 1738                         xpp.red = true; 1739                         x = xpp; 1740  } 1741                     else { 1742                         if (x == xp.right) { 1743                             root = rotateLeft(root, x = xp); 1744                             xpp = (xp = x.parent) == null ? null : xp.parent; 1745  } 1746                         if (xp != null) { 1747                             xp.red = false; 1748                             if (xpp != null) { 1749                                 xpp.red = true; 1750                                 root = rotateRight(root, xpp); 1751  } 1752  } 1753  } 1754  } 1755                 else { 1756                     if (xppl != null && xppl.red) { 1757                         xppl.red = false; 1758                         xp.red = false; 1759                         xpp.red = true; 1760                         x = xpp; 1761  } 1762                     else { 1763                         if (x == xp.left) { 1764                             root = rotateRight(root, x = xp); 1765                             xpp = (xp = x.parent) == null ? null : xp.parent; 1766  } 1767                         if (xp != null) { 1768                             xp.red = false; 1769                             if (xpp != null) { 1770                                 xpp.red = true; 1771                                 root = rotateLeft(root, xpp); 1772  } 1773  } 1774  } 1775  } 1776  } 1777  } 1778 
1779         static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root, 1780                                                    TreeNode<K,V> x) { 1781             for (TreeNode<K,V> xp, xpl, xpr;;) { 1782                 if (x == null || x == root) 1783                     return root; 1784                 else if ((xp = x.parent) == null) { 1785                     x.red = false; 1786                     return x; 1787  } 1788                 else if (x.red) { 1789                     x.red = false; 1790                     return root; 1791  } 1792                 else if ((xpl = xp.left) == x) { 1793                     if ((xpr = xp.right) != null && xpr.red) { 1794                         xpr.red = false; 1795                         xp.red = true; 1796                         root = rotateLeft(root, xp); 1797                         xpr = (xp = x.parent) == null ? null : xp.right; 1798  } 1799                     if (xpr == null) 1800                         x = xp; 1801                     else { 1802                         TreeNode<K,V> sl = xpr.left, sr = xpr.right; 1803                         if ((sr == null || !sr.red) &&
1804                             (sl == null || !sl.red)) { 1805                             xpr.red = true; 1806                             x = xp; 1807  } 1808                         else { 1809                             if (sr == null || !sr.red) { 1810                                 if (sl != null) 1811                                     sl.red = false; 1812                                 xpr.red = true; 1813                                 root = rotateRight(root, xpr); 1814                                 xpr = (xp = x.parent) == null ?
1815                                     null : xp.right; 1816  } 1817                             if (xpr != null) { 1818                                 xpr.red = (xp == null) ? false : xp.red; 1819                                 if ((sr = xpr.right) != null) 1820                                     sr.red = false; 1821  } 1822                             if (xp != null) { 1823                                 xp.red = false; 1824                                 root = rotateLeft(root, xp); 1825  } 1826                             x = root; 1827  } 1828  } 1829  } 1830                 else { 1831                     if (xpl != null && xpl.red) { 1832                         xpl.red = false; 1833                         xp.red = true; 1834                         root = rotateRight(root, xp); 1835                         xpl = (xp = x.parent) == null ? null : xp.left; 1836  } 1837                     if (xpl == null) 1838                         x = xp; 1839                     else { 1840                         TreeNode<K,V> sl = xpl.left, sr = xpl.right; 1841                         if ((sl == null || !sl.red) &&
1842                             (sr == null || !sr.red)) { 1843                             xpl.red = true; 1844                             x = xp; 1845  } 1846                         else { 1847                             if (sl == null || !sl.red) { 1848                                 if (sr != null) 1849                                     sr.red = false; 1850                                 xpl.red = true; 1851                                 root = rotateLeft(root, xpl); 1852                                 xpl = (xp = x.parent) == null ?
1853                                     null : xp.left; 1854  } 1855                             if (xpl != null) { 1856                                 xpl.red = (xp == null) ? false : xp.red; 1857                                 if ((sl = xpl.left) != null) 1858                                     sl.red = false; 1859  } 1860                             if (xp != null) { 1861                                 xp.red = false; 1862                                 root = rotateRight(root, xp); 1863  } 1864                             x = root; 1865  } 1866  } 1867  } 1868  } 1869  } 1870 
1871         static <K,V> boolean checkInvariants(TreeNode<K,V> t) { 1872             TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right, 1873                 tb = t.prev, tn = (TreeNode<K,V>)t.next; 1874             if (tb != null && tb.next != t) 1875                 return false; 1876             if (tn != null && tn.prev != t) 1877                 return false; 1878             if (tp != null && t != tp.left && t != tp.right) 1879                 return false; 1880             if (tl != null && (tl.parent != t || tl.hash > t.hash)) 1881                 return false; 1882             if (tr != null && (tr.parent != t || tr.hash < t.hash)) 1883                 return false; 1884             if (t.red && tl != null && tl.red && tr != null && tr.red) 1885                 return false; 1886             if (tl != null && !checkInvariants(tl)) 1887                 return false; 1888             if (tr != null && !checkInvariants(tr)) 1889                 return false; 1890             return true; 1891  } 1892  } 1893 
1894 }

HashMap的put方法:node

HashMap按value排序:算法

 

 1 import java.util.*;  2 
 3 public class Demo {  4     public static void main(String[] args) {  5         Map<String, Integer> map = new HashMap<>();  6         map.put("a", 1);  7         map.put("c", 3);  8         map.put("b", 5);  9         map.put("f", 7); 10         map.put("e", 6); 11         map.put("d", 8); 12         List<Map.Entry<String, Integer>> list = new ArrayList<>(map.entrySet()); 13         list.sort((m, n) -> n.getValue() - m.getValue()); 14 
15         for (Map.Entry<String, Integer> entry : list) { 16             System.out.println(entry.getKey() + "=" + entry.getValue()); 17  } 18  } 19 } 20 /**
21  * d=8 22  * f=7 23  * e=6 24  * b=5 25  * c=3 26  * a=1 27  */
相關文章
相關標籤/搜索