java.util.HashMap  类继承了 java.util.AbstractMap  抽象类,实现了 java.util.Map 、java.lang.Cloneable 、java.io.Serializable  接口。
 
一、HashMap特点或规范 二、成员属性 三、构造器 四、内部类:Node,即:Map.Entry 五、继承自AbstractMap的方法 六、实现自Map接口的方法 七、静态工具方法 八、其他主要方法 九、迭代器 十、红 黑 树 
 
HashMap  是基于 哈希表  的 Map 接口实现。无序  且不保证顺序永远保持不变。
1.1 与Hashtable的区别 
HashMap 
Hashtable 
 
 
不同步 
同步 
 
允许空键 
不允许空键 
 
允许空值 
不允许空值 
 
1.2 性能 
通常情况下,hash(Object)  方法计算得出的哈希值都均匀的分布在 哈希桶  之间,这样可以保证 get(K)  和 put(K, V)  基本操作方法的性能为恒定时间。 
对集合视图:keySet() ,values() ,entrySet()  的 迭代时间 ,与 HashMap实例的容量(桶的数量)加上其大小(K-V Node 的数量)成比例的时间。因此,如果迭代性能有较高要求,则不要将 初始容量设置得太高 或 负载因子设置得太低。 
影响 HashMap 性能的两个因素:初始容量  和 负载因子 。 
 
1.3 容量capacity & 加载因子loadFactor 
容量 :哈希表中的桶数,初始容量只是创建 HashMap 时的容量。 
加载因子 :是一个比例值,即:已被分布的哈希桶数 / 容量;也可以描述为:扩容操作之前允许哈希桶中已被分布的桶的数量 。 
 
当 HashMap 中已被分布的桶数超过了 加载因子 * 当前容量  时,HashMap将被扩容至原来容量的两倍,并重新计算哈希值(即,重建内部数据结构)。
默认加载因子为:0.75 ,这个值在时间和空间成本之间提供了良好的权衡。 较高的值会减少空间开销,但会增加查找成本。在设置初始容量时,应考虑 Map 中的预期 Entry 数及加载因子,以避免多次扩容带来的性能损耗。 如果要将一个包含多个 Entry 的 Map 存储在 HashMap 中,应使用足够大的初始容量来创建,否则 HashMap 自身的扩容机制会多次进行扩容,严重影响性能。
1.4 HashMap的数据结构 1.4.1 hash算法 HashMap 是通过对 key 进行 hash() 计算得出该节点(Node) 在 table 中的位置。详情:hash(Object)方法  。
1.4.2 hash冲突及常见解决办法 当 HashMap 中节点过多时,不可避免的会出现 hash 冲突的问题,常见解决办法有两类:
开放定址法 :又有两种:
线性探测 :当 hash 冲突时,查找下一个位置是否被占用,如果被占用则继续查找下一个位置,直到找到空位置。
 
平方探测 :以平方大小查找下一个位置,假如:在2位置处发生冲突,则探测 (1^2)+1=3 位置处,如果3位置处也被占用,则探测 (2^2)+2=6 位置处,(3^2)+2=11 …
缺点:虽然效率有所提升,但会浪费空间;在哈希表未满的情况下,可能无法继续放入新元素。 
 
 
 
 
链地址法 :HashMap 就采用了这种方式。
这种方式的哈希表有一个桶 的概念,即:哈希桶 ,每一个链表就是一个哈希桶,链表中存放节点 Node。当发生 hash 冲突时,放入当前链表的末尾。 
 
 
 
1.4.3 红 黑树 当哈希表某一位置处的链表达到 8 个以上,并且哈希表的长度大于 64,该位置的链表会转换为一种 平衡二叉树 :红黑树  。
1.5 HashMap不同步 如果多个线程并发访问 HashMap ,并且至少有一个线程在结构上进行了修改,则必须在外部进行同步。结构修改  是指 添加 或 删除  一个或多个 Entry  的任何操作,仅修改 Entry  的值不是结构修改。这通常通过同步自然封装映射的某个对象来完成。
正确的同步方式:
Map m = Collections.synchronizedMap(new HashMap(...));
1.6 fail-fast快速失败机制 HashMap  的所有“集合视图方法”返回的迭代器都是 fail-fast   的:如果在创建迭代器之后的任何时候对 Map 进行结构修改,除了通过迭代器自己的 remove()  方法之外,迭代器将抛出 ConcurrentModificationException  异常。因此,在并发修改的情况下,迭代器可快速地失败。
 
默认初始容量,必须是2的幂。
1 static  final  int  DEFAULT_INITIAL_CAPACITY  =  1  << 4 ; 
 
最大容量,2的30次幂。
1 static  final  int  MAXIMUM_CAPACITY  =  1  << 30 ; 
 
默认加载因子:0.75f。
1 static  final  float  DEFAULT_LOAD_FACTOR  =  0.75f ;
 
链表中 Entry 数大于8时,将转为 红 黑树  结构。
1 static  final  int  TREEIFY_THRESHOLD  =  8 ;
 
红 黑树  转化为链表的长度临界值
1 static  final  int  UNTREEIFY_THRESHOLD  =  6 ;
 
转化 红 黑树  的最小数组长度为64,数组长度太小不会转化红黑树。
1 static  final  int  MIN_TREEIFY_CAPACITY  =  64 ;
 
HashMap 的基础数组结构,存放 Node 根节点。
1 transient  Node<K,V>[] table;
 
存放 HashMap 中全部 Entry 的 Set 集合
1 transient  Set<Map.Entry<K,V>> entrySet;
 
大小:HashMap 的 Entry 数量
 
被修改或删除的总次数
 
阈,临界值,当 HashMap 的大小达到临界值时,需要扩容
 
加载因子
 
 
3.1 遵循Map接口的构造器规范 java.util.Map  接口的构造器规范,提供一个 无参构造器 ,一个 参数类型为 Map  的构造器。初始加载因子为默认值:0.75,其余值都为默认值。
1 2 3 4 5 6 7 8 public  HashMap ()  {     this .loadFactor = DEFAULT_LOAD_FACTOR; }public  HashMap (Map<? extends K, ? extends V> m)  {     this .loadFactor = DEFAULT_LOAD_FACTOR;          putMapEntries(m, false ); }
 
3.2 HashMap自身构造器 支持指定 初始容量 ,加载因子为默认值:0.75 
1 2 3 public  HashMap (int  initialCapacity)  {     this (initialCapacity, DEFAULT_LOAD_FACTOR); }
 
支持指定 初始容量  及 加载因子 。
1 2 3 4 5 6 7 8 9 10 11 12 13 public  HashMap (int  initialCapacity, float  loadFactor)  {          if  (initialCapacity < 0 )         throw  new  IllegalArgumentException ("Illegal initial capacity: "  + initialCapacity);          if  (initialCapacity > MAXIMUM_CAPACITY)         initialCapacity = MAXIMUM_CAPACITY;          if  (loadFactor <= 0  || Float.isNaN(loadFactor))         throw  new  IllegalArgumentException ("Illegal load factor: "  + loadFactor);     this .loadFactor = loadFactor;     this .threshold = tableSizeFor(initialCapacity); }
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 static  class  Node <K,V> implements  Map .Entry<K,V> {          final  int  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; }     public  final  int  hashCode ()  {         return  Objects.hashCode(key) ^ Objects.hashCode(value);     }          public  final  V setValue (V newValue)  {         V  oldValue  =  value;         value = newValue;         return  oldValue;     }     public  final  boolean  equals (Object o)  {         if  (o == this ) { return  true ; }         if  (o instanceof  Map.Entry) {             Map.Entry<?,?> e = (Map.Entry<?,?>)o;                          if  (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) {                 return  true ;             }         }         return  false ;     } }
 
 
5.1 基础操作 对 HashMap 的基础操作,依赖于 hash() / getNode() / putVal() / putMapEntries() / removeNode()  方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public  int  size ()  { return  size; }public  boolean  isEmpty ()  { return  size == 0 ; }public  V get (Object key)  {     Node<K,V> e;      return  (e = getNode(hash(key), key)) == null  ? null  : e.value; }public  boolean  containsKey (Object key)  {     return  getNode(hash(key), key) != null ; }public  V put (K key, V value)  {     return  putVal(hash(key), key, value, false , true ); }public  void  putAll (Map<? extends K, ? extends V> m)  {     putMapEntries(m, true ); }public  V remove (Object key)  {     Node<K,V> e;     return  (e = removeNode(hash(key), key, null , false , true )) == null  ? null  : e.value; }public  void  clear ()  {     Node<K,V>[] tab;     modCount++;     if  ((tab = table) != null  && size > 0 ) {         size = 0 ;         for  (int  i  =  0 ; i < tab.length; ++i)             tab[i] = null ;     } }public  boolean  containsValue (Object value)  {     Node<K,V>[] tab; V v;     if  ((tab = table) != null  && size > 0 ) {         for  (int  i  =  0 ; i < tab.length; ++i) {             for  (Node<K,V> e = tab[i]; e != null ; e = e.next) {                 if  ((v = e.value) == value ||                     (value != null  && value.equals(v)))                     return  true ;             }         }     }     return  false ; }@Override public  Object clone ()  {     HashMap<K,V> result;     try  {         result = (HashMap<K,V>)super .clone();     } catch  (CloneNotSupportedException e) {         throw  new  InternalError (e);     }     result.reinitialize();     result.putMapEntries(this , false );     return  result; }
 
5.2 转换为单列集合视图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public  Set<K> keySet ()  {     Set<K> ks;     return  (ks = keySet) == null  ? (keySet = new  KeySet ()) : ks; }public  Collection<V> values ()  {     Collection<V> vs;     return  (vs = values) == null  ? (values = new  Values ()) : vs; }public  Set<Map.Entry<K,V>> entrySet() {     Set<Map.Entry<K,V>> es;     return  (es = entrySet) == null  ? (entrySet = new  EntrySet ()) : es; }
 
 
6.1 覆盖扩展自 JDK8 Map 的默认方法。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  V getOrDefault (Object key, V defaultValue)  {}public  V putIfAbsent (K key, V value)  {}public  boolean  remove (Object key, Object value)  {}public  boolean  replace (K key, V oldValue, V newValue)  {}public  V replace (K key, V value)  {}public  void  forEach (BiConsumer<? super  K, ? super  V> action)  {}public  void  replaceAll (BiFunction<? super  K, ? super  V, ? extends V> function)  {}
 
lambda表达式计算操作的方法 
具体说明以下方法的作用,测试数据:
1 2 3 4 Map<Integer, String> map = new  HashMap <>(); map.put(1 , "a" ); map.put(2 , "b" ); map.put(3 , "c" );
 
computeIfAbsent() 如果 key 存在,则不进行计算,输出旧值。 如果 key 不存在,否则根据 key 计算新值,设置并返回。
1 2 3 public  V computeIfAbsent (K key, Function<? super  K, ? extends V> mappingFunction)  {} map.computeIfAbsent(3 , key -> key.toString());  map.computeIfAbsent(4 , key -> key.toString()); 
 
computeIfPresent() 如果 key 存在,则根据 key/value 计算新的值,设置并返回,如果计算结果为 null,则删除 Node。 如果 key 不存在,不进行计算。
1 2 3 4 public  V computeIfPresent (K key, BiFunction<? super  K, ? super  V, ? extends V> remappingFunction)  {} map.computeIfPresent(3 , (key, value) -> key + value);  map.computeIfPresent(4 , (key, value) -> key + value);  map.computeIfPresent(2 , (key, value) -> null ); 
 
compute() compute()  方法是 computeIfAbsent()  和 computeIfPresent()  方法的合体。 无论 key 是否存在,都根据 key/value 计算新值,如果计算结果为 null,则删除 Node。
1 2 3 4 public  V compute (K key, BiFunction<? super  K, ? super  V, ? extends V> remappingFunction)  {} map.compute(3 , (k, v) -> k + v);  map.compute(4 , (k, v) -> k + v);  map.compute(2 , (k, v) -> null ); 
 
merge() 无论 key 是否存在,都根据 旧值  与 新值  进行计算,设置并返回计算结果,如果计算结果为 null,则删除 Node。
1 2 3 4 public  V merge (K key, V value, BiFunction<? super  V, ? super  V, ? extends V> remappingFunction)  {} map.merge(3 , "ccc" , (oldV, newV) -> oldV + newV);  map.merge(4 , "ddd" , (oldV, newV) -> oldV + newV);  map.merge(2 , "bbb" , (oldV, newV) -> null ); 
 
 
对 key 计算 hashCode 计算,int 类型的 hashCode 占 32 位,h >>> 16  将 hashCode 右移16位,再与 hashCode 进行异或运算。
1 2 3 4 5 6 7 8 static  final  int  hash (Object key)  {     int  h;     return  (key == null ) ? 0  : (h = key.hashCode()) ^ (h >>> 16 ); } n = tab.length tab[(n - 1 ) & hash]
 
原因 :高16位与低16位进行异或运算,可以将高位上的变化体现到低位上,以此来避免 hash 碰撞,同时又保证了性能。getNode()  方法根据 table 的最后一个索引值 与 hash  进行 与运算 ,将结果作为数组的索引进行取值。
1 2 3 4 5 6 7 8 9 10 0000  0000  0000  0000  0000  0000  0001  0000        1111  1111  1111  1111  0000  1010  0011  1010        0000  0000  0000  0000  1111  1111  1111  1111        1111  1111  1111  1111  1111  0101  1100  0101        0000  0000  0000  0000  0000  0000  0000  1111        1111  1111  1111  1111  1111  0101  1100  0101        0000  0000  0000  0000  0000  0000  0000  0101        
 
只有最低的4位参与了计算,该 key 在 table 的 tab[5] 位置 。
7.2 tableSizeFor(int) 方法 此方法保证返回值是大于等于给定参数 cap 最小的2的幂次方的数值。具体算法是分别进行多次 右移 ,每次进行 或等运算 。
1 2 3 4 5 6 7 8 9 static  final  int  tableSizeFor (int  cap)  {     int  n  =  cap - 1 ;     n |= n >>> 1 ;     n |= n >>> 2 ;     n |= n >>> 4 ;     n |= n >>> 8 ;     n |= n >>> 16 ;     return  (n < 0 ) ? 1  : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1 ; }
 
假如,给定的初始化容量是10:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 0000  1010       0000  1001       0000  1001       0000  0100       0000  1101       0000  1101       0000  0011       0000  1111       0000  1111       0000  0000       0000  1111       0000  1111       0000  0000       0000  1111       0000  1111       0000  0000       0000  1111       0001  0000       
 
 
putMapEntries(Map, boolean) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 final  void  putMapEntries (Map<? extends K, ? extends V> m, boolean  evict)  {     int  s  =  m.size();     if  (s > 0 ) {         if  (table == null ) {                          float  ft  =  ((float )s / loadFactor) + 1.0F ;             int  t  =  ((ft < (float )MAXIMUM_CAPACITY) ? (int )ft : MAXIMUM_CAPACITY);             if  (t > threshold)                 threshold = tableSizeFor(t);         } else  if  (s > threshold) {             resize();         }         for  (Map.Entry<? extends  K , ? extends  V > e : m.entrySet()) {             K  key  =  e.getKey();             V  value  =  e.getValue();             putVal(hash(key), key, value, false , evict);         }     } }
 
getNode(int, Object) 执行过程分析: 
根据 (tab.length - 1) & hash  计算出元素在 table 中的索引位置,优先判断第一个:
如果第一个是要找的元素,返回该元素。 
如果第一个不是要找的元素,则判断该节点是链表结构,还是树型结构:
如果是树型结构,根据 hash、key查找。 
如果是链表结构,循环迭代 netx 节点,直到找到该元素。 
 
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 final  Node<K,V> getNode (int  hash, Object key)  {     Node<K,V>[] tab; Node<K,V> first, e; int  n; K k;     if  ((tab = table) != null  && (n = tab.length) > 0  &&         (first = tab[(n - 1 ) & hash]) != null ) {         if  (first.hash == hash &&              ((k = first.key) == key || (key != null  && key.equals(k))))             return  first;         if  ((e = first.next) != null ) {             if  (first instanceof  TreeNode)                  return  ((TreeNode<K,V>)first).getTreeNode(hash, key);             do  {                 if  (e.hash == hash &&                     ((k = e.key) == key || (key != null  && key.equals(k))))                     return  e;             } while  ((e = e.next) != null );          }     }     return  null ; }
 
putVal(int, K, V, boolean, boolean) 方法 执行过程分析: 
先判断 table 是否为空,如果为空,进行扩容。 
根据 (tab.length - 1) & hash  计算出元素在 table 中的索引,并判断是否为空: 
 
第一个节点为空,说明该 hash 桶下没有任何节点,直接放入即可。 
第一个节点不为空:
当前节点与该位置的第一个节点的 hash 值一致,key 也相同,已存在。 
判断该位置的结构:
树型结构:调用 putTreeVal()  放入。 
链表结构:将该节点放入第一个节点的 next 位置,并检查是否需要转化为树型结构。 
 
 
 
 
 
自增修改次数、size 大小,并判断 size 是否大于当前临界值,即:是否需要扩容。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 final  V putVal (int  hash, K key, V value, boolean  onlyIfAbsent, boolean  evict)  {     Node<K,V>[] tab;     Node<K,V> p;     int  n, i;     if  ((tab = table) == null  || (n = tab.length) == 0 )         n = (tab = resize()).length;      if  ((p = tab[i = (n - 1 ) & hash]) == null )          tab[i] = newNode(hash, key, value, null );     else  {         Node<K,V> e; K k;         if  (p.hash == hash && ((k = p.key) == key || (key != null  && key.equals(k))))             e = p;         else  if  (p instanceof  TreeNode)             e = ((TreeNode<K,V>)p).putTreeVal(this , tab, hash, key, value);         else  {             for  (int  binCount  =  0 ; ; ++binCount) {                 if  ((e = p.next) == null ) {                     p.next = newNode(hash, key, value, null );                     if  (binCount >= TREEIFY_THRESHOLD - 1 )                          treeifyBin(tab, hash);                     break ;                 }                 if  (e.hash == hash &&                     ((k = e.key) == key || (key != null  && key.equals(k))))                     break ;                 p = e;             }         }         if  (e != null ) {              V  oldValue  =  e.value;             if  (!onlyIfAbsent || oldValue == null )                 e.value = value;             afterNodeAccess(e);             return  oldValue;         }     }     ++modCount;     if  (++size > threshold) { resize(); }     afterNodeInsertion(evict);     return  null ; }
 
resize() 方法 执行过程分析: 
先判断旧容量是否大于 0: 
 
如果旧容量大于 0,说明 table 已初始化,继续判断:
如果旧容量大于等于最大容量限制,将临界值 threshold  设置为 Integer.MAX_VALUE 。 
如果将容量扩容 2 倍后小于最大容量限制,且旧容量大于等于初始容量 16,则扩容旧临界值为原来的 2 倍。 
 
 
如果旧容量不大于 0,说明 table 未初始化,继续判断:
如果旧临界值大于 0,将旧临界值赋值给新容量,HashMap  初始化时,临界值为16。 
否则就初始化默认参数。 
 
 
 
再次校验新临界值是否为 0,如果为 0,初始化临界值 。 
创建一个新 Node 数组,并循环复制全部节点: 
 
如果循环中的当前位置只有一个节点,则直接赋值。 
如果循环中的当前位置是红黑树,调用 split()  方法。 
如果循环中的当前位置是链表,则复制并重新计算 hash 值。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 final  Node<K,V>[] resize() {     Node<K,V>[] oldTab = table;     int  oldCap  =  (oldTab == null ) ? 0  : oldTab.length;     int  oldThr  =  threshold;     int  newCap, newThr = 0 ;          if  (oldCap > 0 ) {         if  (oldCap >= MAXIMUM_CAPACITY) {                          threshold = Integer.MAX_VALUE;             return  oldTab;         }         else  if  ((newCap = oldCap << 1 ) < MAXIMUM_CAPACITY &&                  oldCap >= DEFAULT_INITIAL_CAPACITY)                                                    newThr = oldThr << 1 ;     }     else  if  (oldThr > 0 )                  newCap = oldThr;     else  {                  newCap = DEFAULT_INITIAL_CAPACITY;         newThr = (int )(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);     }     if  (newThr == 0 ) {                  float  ft  =  (float )newCap * loadFactor;         newThr = (newCap < MAXIMUM_CAPACITY && ft < (float )MAXIMUM_CAPACITY ?                   (int )ft : Integer.MAX_VALUE);     }     threshold = newThr;          Node<K,V>[] newTab = (Node<K,V>[])new  Node [newCap];     table = newTab;     if  (oldTab != null ) {                  for  (int  j  =  0 ; j < oldCap; ++j) {             Node<K,V> e;             if  ((e = oldTab[j]) != null ) {                 oldTab[j] = null ;                 if  (e.next == null )                                          newTab[e.hash & (newCap - 1 )] = e;                 else  if  (e instanceof  TreeNode)                                          ((TreeNode<K,V>)e).split(this , newTab, j, oldCap);                 else  {                      Node<K,V> loHead = null , loTail = null ;                     Node<K,V> hiHead = null , hiTail = null ;                     Node<K,V> next;                     do  {                         next = e.next;                         if  ((e.hash & oldCap) == 0 ) {                             if  (loTail == null )                                 loHead = e;                             else                                  loTail.next = e;                             loTail = e;                         }                         else  {                             if  (hiTail == null )                                 hiHead = e;                             else                                  hiTail.next = e;                             hiTail = e;                         }                     } while  ((e = next) != null );                     if  (loTail != null ) {                         loTail.next = null ;                         newTab[j] = loHead;                     }                     if  (hiTail != null ) {                         hiTail.next = null ;                         newTab[j + oldCap] = hiHead;                     }                 }             }         }     }     return  newTab; }
 
removeNode(int, Object, Object, boolean, boolean) 方法 核心删除方法,其他 remove 方法都依赖于此方法。执行过程分析: 
首先执行的前提是 table 已初始化,且不为空。 
根据 hash 值计算出的位置,确定该位置处是一个节点,红黑树还是链表,并查找。 
删除,判断该位置的类型,执行不同的删除方式。 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 final  Node<K,V> removeNode (int  hash, Object key, Object value,                            boolean  matchValue, boolean  movable)  {     Node<K,V>[] tab; Node<K,V> p; int  n, index;     if  ((tab = table) != null  && (n = tab.length) > 0  &&         (p = tab[index = (n - 1 ) & hash]) != null ) {         Node<K,V> node = null , e; K k; V v;         if  (p.hash == hash &&             ((k = p.key) == key || (key != null  && key.equals(k))))                          node = p;         else  if  ((e = p.next) != null ) {             if  (p instanceof  TreeNode)                                  node = ((TreeNode<K,V>)p).getTreeNode(hash, key);             else  {                                  do  {                     if  (e.hash == hash &&                         ((k = e.key) == key ||                          (key != null  && key.equals(k)))) {                         node = e;                         break ;                     }                     p = e;                 } while  ((e = e.next) != null );             }         }         if  (node != null  && (!matchValue || (v = node.value) == value ||                              (value != null  && value.equals(v)))) {             if  (node instanceof  TreeNode)                 ((TreeNode<K,V>)node).removeTreeNode(this , tab, movable);             else  if  (node == p)                 tab[index] = node.next;             else                  p.next = node.next;             ++modCount;             --size;             afterNodeRemoval(node);             return  node;         }     }     return  null ; }
 
 
keySet() ,values() ,entrySet()  三个视图方法中的迭代器都为 HashIterator  抽象类的实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 abstract  class  HashIterator  {     Node<K,V> next;             Node<K,V> current;          int  expectedModCount;       int  index;                  HashIterator() {         expectedModCount = modCount;         Node<K,V>[] t = table;         current = next = null ;         index = 0 ;         if  (t != null  && size > 0 ) {              do  {} while  (index < t.length && (next = t[index++]) == null );         }     }     public  final  boolean  hasNext ()  { return  next != null ; }     final  Node<K,V> nextNode ()  {         Node<K,V>[] t;         Node<K,V> e = next;         if  (modCount != expectedModCount)             throw  new  ConcurrentModificationException ();         if  (e == null )             throw  new  NoSuchElementException ();         if  ((next = (current = e).next) == null  && (t = table) != null ) {             do  {} while  (index < t.length && (next = t[index++]) == null );         }         return  e;     }     public  final  void  remove ()  {         Node<K,V> p = current;         if  (p == null )             throw  new  IllegalStateException ();         if  (modCount != expectedModCount)             throw  new  ConcurrentModificationException ();         current = null ;         K  key  =  p.key;         removeNode(hash(key), key, null , false , false );         expectedModCount = modCount;     } }
 
1 2 3 4 5 6 7 8 9 10 11 12 final  class  KeyIterator  extends  HashIterator  implements  Iterator <K> {     public  final  K next ()  { return  nextNode().key; } }final  class  ValueIterator  extends  HashIterator  implements  Iterator <V> {     public  final  V next ()  { return  nextNode().value; } }final  class  EntryIterator  extends  HashIterator  implements  Iterator <Map.Entry<K,V>> {     public  final  Map.Entry<K,V> next ()  { return  nextNode(); } }