• 3.1HashMap源码分析


    在前篇博文中(HashMap原理及实现学习总结)详细总结了HashMap的原理及实现过程,这一篇是对HashMap的源码分析。

      1 package dataStructure.hash;
      2 
      3 import java.io.*;
      4 import java.util.AbstractCollection;
      5 import java.util.AbstractMap;
      6 import java.util.AbstractSet;
      7 import java.util.Collection;
      8 import java.util.ConcurrentModificationException;
      9 import java.util.Iterator;
     10 import java.util.Map;
     11 import java.util.NoSuchElementException;
     12 import java.util.Set;
     13 
     14 public class HashMap<K, V> extends AbstractMap<K, V>implements Map<K, V>, Cloneable, Serializable {
     15 
     16     // 系统默认初始容量,必须是2的n次幂,这是出于优化考虑的
     17     static final int DEFAULT_INITIAL_CAPACITY = 16;
     18 
     19     // 系统默认最大容量
     20     static final int MAXIMUM_CAPACITY = 1 << 30;
     21 
     22     // 系统默认负载因子,可在构造函数中指定
     23     static final float DEFAULT_LOAD_FACTOR = 0.75f;
     24 
     25     // 用于存储的表,长度可以调整,且必须是2的n次幂
     26     transient Entry[] table;
     27 
     28     // 当前map的key-value映射数,也就是当前size
     29     transient int size;
     30 
     31     // 阈值
     32     int threshold;
     33 
     34     // 哈希表的负载因子
     35     final float loadFactor;
     36 
     37     // 用于确保使用迭代器的时候,HashMap并未进行更改
     38     transient volatile int modCount;
     39 
     40     // 构造一个带指定初始容量和加载因子的空 HashMap。
     41     public HashMap(int initialCapacity, float loadFactor) {
     42         // 如果指定初始容量小于0,抛错
     43         if (initialCapacity < 0)
     44             throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
     45         // 如果初始容量大于系统默认最大容量,则初始容量为最大容量
     46         if (initialCapacity > MAXIMUM_CAPACITY)
     47             initialCapacity = MAXIMUM_CAPACITY;
     48         // 如果loadFactor小于0,或loadFactor是NaN,则抛错
     49         if (loadFactor <= 0 || Float.isNaN(loadFactor))
     50             throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
     51 
     52         // 寻找一个2的k次幂capacity恰好大于initialCapacity
     53         int capacity = 1;
     54         while (capacity < initialCapacity)
     55             capacity <<= 1;
     56 
     57         // 设置加载因子
     58         this.loadFactor = loadFactor;
     59         // 设置阈值为capacity * loadFactor,实际上当HashMap当前size到达这个阈值时,HashMap就需要扩大一倍了。
     60         threshold = (int) (capacity * loadFactor);
     61         // 创建一个capacity长度的数组用于保存数据
     62         table = new Entry[capacity];
     63         // 开始初始化
     64         init();
     65     }
     66 
     67     // 构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。
     68     public HashMap(int initialCapacity) {
     69         this(initialCapacity, DEFAULT_LOAD_FACTOR);
     70     }
     71 
     72     // 构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
     73     public HashMap() {
     74         this.loadFactor = DEFAULT_LOAD_FACTOR;
     75         threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
     76         table = new Entry[DEFAULT_INITIAL_CAPACITY];
     77         init();
     78     }
     79 
     80     // 构造一个映射关系与指定 Map 相同的新 HashMap。
     81     public HashMap(Map<? extends K, ? extends V> m) {
     82         this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
     83         putAllForCreate(m);
     84     }
     85 
     86     // 内部公用工具
     87 
     88     // 定义一个空方法用于未来的子对象扩展,该方法用于初始化之后,插入元素之前
     89     void init() {
     90     }
     91 
     92     // 预处理hash值,避免较差的离散hash序列,导致桶没有充分利用
     93     static int hash(int h) {
     94         h ^= (h >>> 20) ^ (h >>> 12);
     95         return h ^ (h >>> 7) ^ (h >>> 4);
     96     }
     97 
     98     // 返回对应hash值得索引
     99     static int indexFor(int h, int length) {
    100         /*****************
    101          * 由于length是2的n次幂,所以h & (length-1)相当于h % length。
    102          * 对于length,其2进制表示为1000...0,那么length-1为0111...1。
    103          * 那么对于任何小于length的数h,该式结果都是其本身h。 对于h = length,该式结果等于0。
    104          * 对于大于length的数h,则和0111...1位与运算后, 比0111...1高或者长度相同的位都变成0,
    105          * 相当于减去j个length,该式结果是h-j*length, 所以相当于h % length。 其中一个很常用的特例就是h & 1相当于h
    106          * % 2。 这也是为什么length只能是2的n次幂的原因,为了优化。
    107          */
    108         return h & (length - 1);
    109     }
    110 
    111     // 返回当前map的key-value映射数,也就是当前size
    112     public int size() {
    113         return size;
    114     }
    115 
    116     // 该HashMap是否是空的,如果size为0,则为空
    117     public boolean isEmpty() {
    118         return size == 0;
    119     }
    120 
    121     // 返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null
    122     public V get(Object key) {
    123         // 若为null,调用getForNullKey方法返回相对应的value 
    124         if (key == null)
    125             return getForNullKey();
    126         // 根据该 key 的 hashCode 值计算它的 hash 码  
    127         int hash = hash(key.hashCode());
    128         // 取出 table 数组中指定索引处的值
    129         for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
    130             Object k;
    131             // 如果hash值相等,并且key相等则证明这个桶里的东西是我们想要的
    132             if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
    133                 return e.value;
    134         }
    135         // 所有桶都找遍了,没找到想要的,所以返回null
    136         return null;
    137     }
    138 
    139     // 如果要得到key为null的值,则通过这个获取
    140     private V getForNullKey() {
    141         // 遍历table[0]里的所有桶
    142         for (Entry<K, V> e = table[0]; e != null; e = e.next) {
    143             // 看看桶的key是不是null,是则返回相应值
    144             if (e.key == null)
    145                 return e.value;
    146         }
    147         // 没找到返回null
    148         return null;
    149     }
    150 
    151     // 如果此映射包含对于指定键的映射关系,则返回true
    152     public boolean containsKey(Object key) {
    153         return getEntry(key) != null;
    154     }
    155 
    156     // 通过key获取一个value
    157     final Entry<K, V> getEntry(Object key) {
    158         // 如果key为null,则hash为0,否则用hash函数预处理
    159         int hash = (key == null) ? 0 : hash(key.hashCode());
    160         // 得到对应的hash值的桶,如果这个桶不是,就通过next获取下一个桶
    161         for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
    162             Object k;
    163             // 如果hash值相等,并且key相等则证明这个桶里的东西是我们想要的
    164             if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
    165                 return e;
    166         }
    167         // 所有桶都找遍了,没找到想要的,所以返回null
    168         return null;
    169     }
    170 
    171     // 在此映射中关联指定值与指定键。如果该映射以前包含了一个该键的映射关系,则旧值被替换
    172     public V put(K key, V value) {
    173         // 当key为null,调用putForNullKey方法,保存null与table第一个位置中,这是HashMap允许为null的原因 
    174         if (key == null)
    175             return putForNullKey(value);
    176         // 使用hash函数预处理hashCode,计算key的hash值  
    177         int hash = hash(key.hashCode());
    178         // 计算key hash 值在 table 数组中的位置 
    179         int i = indexFor(hash, table.length);
    180         // 从i出开始迭代 e,找到 key 保存的位置
    181         for (Entry<K, V> e = table[i]; e != null; e = e.next) {
    182             Object k;
    183             // 判断该条链上是否有hash值相同的(key相同) 
    184             // 若存在相同,则直接覆盖value,返回旧value 
    185             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    186                 // 旧值 = 新值  
    187                 V oldValue = e.value;
    188                 // 将要存储的value存进去
    189                 e.value = value;
    190                 e.recordAccess(this);
    191                 // 返回旧的value
    192                 return oldValue;
    193             }
    194         }
    195         // 修改次数增加1 
    196         modCount++;
    197         // 将key、value添加至i位置处 
    198         addEntry(hash, key, value, i);
    199         return null;
    200     }
    201 
    202     // key为null怎么放value
    203     private V putForNullKey(V value) {
    204         // 遍历table[0]的所有桶
    205         for (Entry<K, V> e = table[0]; e != null; e = e.next) {
    206             // 如果key是null
    207             if (e.key == null) {
    208                 // 取出oldValue,并存入value
    209                 V oldValue = e.value;
    210                 e.value = value;
    211                 e.recordAccess(this);
    212                 // 返回oldValue
    213                 return oldValue;
    214             }
    215         }
    216         modCount++;
    217         addEntry(0, null, value, 0);
    218         return null;
    219     }
    220 
    221     // 看看需不需要创建新的桶
    222     private void putForCreate(K key, V value) {
    223         // 如果key为null,则定义hash为0,否则用hash函数预处理
    224         int hash = (key == null) ? 0 : hash(key.hashCode());
    225         // 获取对应的索引
    226         int i = indexFor(hash, table.length);
    227 
    228         // 遍历所有桶
    229         for (Entry<K, V> e = table[i]; e != null; e = e.next) {
    230             Object k;
    231             // 如果有hash相同,且key相同,那么则不需要创建新的桶,退出
    232             if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {
    233                 e.value = value;
    234                 return;
    235             }
    236         }
    237 
    238         // 否则需要创建新的桶
    239         createEntry(hash, key, value, i);
    240     }
    241 
    242     // 根据Map创建所有对应的桶
    243     private void putAllForCreate(Map<? extends K, ? extends V> m) {
    244         for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext();) {
    245             Map.Entry<? extends K, ? extends V> e = i.next();
    246             putForCreate(e.getKey(), e.getValue());
    247         }
    248     }
    249 
    250     // 更具新的容量来resize这个HashMap
    251     void resize(int newCapacity) {
    252         // 保存oldTable
    253         Entry[] oldTable = table;
    254         // 保存旧的容量
    255         int oldCapacity = oldTable.length;
    256         // 如果旧的容量已经是系统默认最大容量了,那么将阈值设置成整形的最大值,退出
    257         if (oldCapacity == MAXIMUM_CAPACITY) {
    258             threshold = Integer.MAX_VALUE;
    259             return;
    260         }
    261 
    262         // 根据新的容量新建一个table
    263         Entry[] newTable = new Entry[newCapacity];
    264         // 将table转换成newTable
    265         transfer(newTable);
    266         // 将table设置newTable
    267         table = newTable;
    268         // 设置阈值
    269         threshold = (int) (newCapacity * loadFactor);
    270     }
    271 
    272     // 将所有格子里的桶都放到新的table中
    273     void transfer(Entry[] newTable) {
    274         // 得到旧的table
    275         Entry[] src = table;
    276         // 得到新的容量
    277         int newCapacity = newTable.length;
    278         // 遍历src里面的所有格子
    279         for (int j = 0; j < src.length; j++) {
    280             // 取到格子里的桶(也就是链表)
    281             Entry<K, V> e = src[j];
    282             // 如果e不为空
    283             if (e != null) {
    284                 // 将当前格子设成null
    285                 src[j] = null;
    286                 // 遍历格子的所有桶
    287                 do {
    288                     // 取出下个桶
    289                     Entry<K, V> next = e.next;
    290                     // 寻找新的索引
    291                     int i = indexFor(e.hash, newCapacity);
    292                     // 设置e.next为newTable[i]保存的桶(也就是链表连接上)
    293                     e.next = newTable[i];
    294                     // 将e设成newTable[i]
    295                     newTable[i] = e;
    296                     // 设置e为下一个桶
    297                     e = next;
    298                 } while (e != null);
    299             }
    300         }
    301     }
    302 
    303     // 将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系
    304     public void putAll(Map<? extends K, ? extends V> m) {
    305         // 看看需要复制多少个映射关系
    306         int numKeysToBeAdded = m.size();
    307         if (numKeysToBeAdded == 0)
    308             return;
    309 
    310         // 如果要复制的映射关系比阈值还要多
    311         if (numKeysToBeAdded > threshold) {
    312             // 重新计算新的容量先resize
    313             int targetCapacity = (int) (numKeysToBeAdded / loadFactor + 1);
    314             if (targetCapacity > MAXIMUM_CAPACITY)
    315                 targetCapacity = MAXIMUM_CAPACITY;
    316             int newCapacity = table.length;
    317             while (newCapacity < targetCapacity)
    318                 newCapacity <<= 1;
    319             if (newCapacity > table.length)
    320                 resize(newCapacity);
    321         }
    322 
    323         // 迭代将key-value映射放进该HashMap
    324         for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext();) {
    325             Map.Entry<? extends K, ? extends V> e = i.next();
    326             put(e.getKey(), e.getValue());
    327         }
    328     }
    329 
    330     // 从此映射中移除指定键的映射关系(如果存在)
    331     public V remove(Object key) {
    332         Entry<K, V> e = removeEntryForKey(key);
    333         return (e == null ? null : e.value);
    334     }
    335 
    336     // 根据key删除桶,并返回对应value
    337     final Entry<K, V> removeEntryForKey(Object key) {
    338         int hash = (key == null) ? 0 : hash(key.hashCode());
    339         int i = indexFor(hash, table.length);
    340         // 找到对应的格子
    341         Entry<K, V> prev = table[i];
    342         Entry<K, V> e = prev;
    343 
    344         // 遍历所有桶
    345         while (e != null) {
    346             Entry<K, V> next = e.next;
    347             Object k;
    348             // 如果找到对应的桶
    349             if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) {
    350                 modCount++;
    351                 // size减1
    352                 size--;
    353                 // 如果第一个就是要删的桶
    354                 if (prev == e)
    355                     // 则table[i]等于下一个桶
    356                     table[i] = next;
    357                 else
    358                     // 否则上一个桶的下一个等于下一个桶
    359                     prev.next = next;
    360                 e.recordRemoval(this);
    361                 return e;
    362             }
    363             prev = e;
    364             e = next;
    365         }
    366 
    367         return e;
    368     }
    369 
    370     // 根据桶来删除map里的值
    371     final Entry<K, V> removeMapping(Object o) {
    372         // 如果o不是Map.Entry的实例,则退出返回null
    373         if (!(o instanceof Map.Entry))
    374             return null;
    375 
    376         // 将o转成Map.Entry
    377         Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
    378         // 得到他的key
    379         Object key = entry.getKey();
    380         // 得到对应的hash
    381         int hash = (key == null) ? 0 : hash(key.hashCode());
    382         // 得到对应的索引
    383         int i = indexFor(hash, table.length);
    384         Entry<K, V> prev = table[i];
    385         Entry<K, V> e = prev;
    386 
    387         // 遍历所有桶
    388         while (e != null) {
    389             Entry<K, V> next = e.next;
    390             // 如果找到对应的桶,则删掉它
    391             if (e.hash == hash && e.equals(entry)) {
    392                 modCount++;
    393                 size--;
    394                 if (prev == e)
    395                     table[i] = next;
    396                 else
    397                     prev.next = next;
    398                 e.recordRemoval(this);
    399                 return e;
    400             }
    401             prev = e;
    402             e = next;
    403         }
    404 
    405         // 并返回该桶
    406         return e;
    407     }
    408 
    409     // 从此映射中移除所有映射关系。此调用返回后,映射将为空
    410     public void clear() {
    411         modCount++;
    412         Entry[] tab = table;
    413         // 遍历table中的所有格子,然偶后设为null
    414         for (int i = 0; i < tab.length; i++)
    415             tab[i] = null;
    416         // 设置size为0
    417         size = 0;
    418     }
    419 
    420     // 如果此映射将一个或多个键映射到指定值,则返回 true
    421     public boolean containsValue(Object value) {
    422         // 如果value为空,则返回containsNullValue函数的返回值
    423         if (value == null)
    424             return containsNullValue();
    425 
    426         Entry[] tab = table;
    427         // 遍历table所有格子(链表)
    428         for (int i = 0; i < tab.length; i++)
    429             // 遍历链表中的每个桶
    430             for (Entry e = tab[i]; e != null; e = e.next)
    431                 // 如果值相同,则返回true
    432                 if (value.equals(e.value))
    433                     return true;
    434         // 否则返回false
    435         return false;
    436     }
    437 
    438     // 对value为null的处理,这里没什么特别的
    439     private boolean containsNullValue() {
    440         Entry[] tab = table;
    441         for (int i = 0; i < tab.length; i++)
    442             for (Entry e = tab[i]; e != null; e = e.next)
    443                 if (e.value == null)
    444                     return true;
    445         return false;
    446     }
    447 
    448     // 返回此 HashMap 实例的浅表副本:并不复制键和值本身
    449     public Object clone() {
    450         HashMap<K, V> result = null;
    451         try {
    452             result = (HashMap<K, V>) super.clone();
    453         } catch (CloneNotSupportedException e) {
    454             // assert false;
    455         }
    456         result.table = new Entry[table.length];
    457         result.entrySet = null;
    458         result.modCount = 0;
    459         result.size = 0;
    460         result.init();
    461         result.putAllForCreate(this);
    462 
    463         return result;
    464     }
    465 
    466     // 内置class输入对象,也就是我们说的桶
    467     static class Entry<K, V> implements Map.Entry<K, V> {
    468         final K key;
    469         V value;
    470         Entry<K, V> next;
    471         final int hash;
    472 
    473         // 构造函数
    474         Entry(int h, K k, V v, Entry<K, V> n) {
    475             value = v;
    476             next = n;
    477             key = k;
    478             hash = h;
    479         }
    480 
    481         // 返回key
    482         public final K getKey() {
    483             return key;
    484         }
    485 
    486         // 返回value
    487         public final V getValue() {
    488             return value;
    489         }
    490 
    491         // 设置value
    492         public final V setValue(V newValue) {
    493             V oldValue = value;
    494             value = newValue;
    495             return oldValue;
    496         }
    497 
    498         // 是否相同
    499         public final boolean equals(Object o) {
    500             // 如果o不是Map.Entry的实例,那么肯定不相同了
    501             if (!(o instanceof Map.Entry))
    502                 return false;
    503             // 将o转成Map.Entry
    504             Map.Entry e = (Map.Entry) o;
    505             // 得到key和value对比是否相同,相同则为true
    506             Object k1 = getKey();
    507             Object k2 = e.getKey();
    508             if (k1 == k2 || (k1 != null && k1.equals(k2))) {
    509                 Object v1 = getValue();
    510                 Object v2 = e.getValue();
    511                 if (v1 == v2 || (v1 != null && v1.equals(v2)))
    512                     return true;
    513             }
    514             // 否则为false
    515             return false;
    516         }
    517 
    518         // hashCode
    519         public final int hashCode() {
    520             return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
    521         }
    522 
    523         // 返回String
    524         public final String toString() {
    525             return getKey() + "=" + getValue();
    526         }
    527 
    528         // 使用该方法证明该key已经在该map中
    529         void recordAccess(HashMap<K, V> m) {
    530         }
    531 
    532         // 该方法记录该key已经被移除了
    533         void recordRemoval(HashMap<K, V> m) {
    534         }
    535     }
    536 
    537     // 添加一个新的桶来保存该key和value
    538     void addEntry(int hash, K key, V value, int bucketIndex) {
    539         // 获取bucketIndex处的Entry 
    540         Entry<K, V> e = table[bucketIndex];
    541         // 将新创建的 Entry 放入 bucketIndex 索引处,并让新的 Entry 指向原来的 Entry  
    542         table[bucketIndex] = new Entry<K, V>(hash, key, value, e);
    543         // 若HashMap中元素的个数超过极限了,则容量扩大两倍 
    544         if (size++ >= threshold)
    545             // 调整容量
    546             resize(2 * table.length);
    547     }
    548 
    549     // 新建一个桶,该方法不需要判断是否超过阈值
    550     void createEntry(int hash, K key, V value, int bucketIndex) {
    551         Entry<K, V> e = table[bucketIndex];
    552         table[bucketIndex] = new Entry<K, V>(hash, key, value, e);
    553         size++;
    554     }
    555 
    556     // 内部class HashIterator迭代器
    557     private abstract class HashIterator<E> implements Iterator<E> {
    558         Entry<K, V> next; // 下一个桶
    559         int expectedModCount; // 保护HashMap没有变更
    560         int index; // 当前的索引
    561         Entry<K, V> current; // 当前的桶
    562 
    563         // 构造方法
    564         HashIterator() {
    565             // 保存modCount,因为如果HashMap进行了任何操作modCount都会增加,所以如果发现modCount变化了,就可以抛出失败
    566             expectedModCount = modCount;
    567             // 进入第一个桶
    568             if (size > 0) {
    569                 Entry[] t = table;
    570                 while (index < t.length && (next = t[index++]) == null)
    571                     ;
    572             }
    573         }
    574 
    575         // 看看有没有下一个桶
    576         public final boolean hasNext() {
    577             return next != null;
    578         }
    579 
    580         // 获取下一个桶
    581         final Entry<K, V> nextEntry() {
    582             // modCount变化了,抛出失败
    583             if (modCount != expectedModCount)
    584                 throw new ConcurrentModificationException();
    585             // 得到next
    586             Entry<K, V> e = next;
    587             // 如果next为空,抛出失败
    588             if (e == null)
    589                 throw new NoSuchElementException();
    590 
    591             // 如果next.next为空,将next定义为下一个格子中的桶,否则为该格子的下一个桶
    592             if ((next = e.next) == null) {
    593                 Entry[] t = table;
    594                 while (index < t.length && (next = t[index++]) == null)
    595                     ;
    596             }
    597             // 给current赋值
    598             current = e;
    599             // 返回e
    600             return e;
    601         }
    602 
    603         // 删除
    604         public void remove() {
    605             // 如果当前为空,抛出
    606             if (current == null)
    607                 throw new IllegalStateException();
    608             // modCount变化了,抛出失败
    609             if (modCount != expectedModCount)
    610                 throw new ConcurrentModificationException();
    611             // 获得当前的key
    612             Object k = current.key;
    613             // 设置current为null
    614             current = null;
    615             // 删除掉对应key的元素
    616             HashMap.this.removeEntryForKey(k);
    617             // 重置expectedModCount
    618             expectedModCount = modCount;
    619         }
    620 
    621     }
    622 
    623     // 内部class ValueIterator迭代器,我们可以看到修改了next方法
    624     private final class ValueIterator extends HashIterator<V> {
    625         public V next() {
    626             return nextEntry().value;
    627         }
    628     }
    629 
    630     // 内部class KeyIterator迭代器,我们可以看到修改了next方法
    631     private final class KeyIterator extends HashIterator<K> {
    632         public K next() {
    633             return nextEntry().getKey();
    634         }
    635     }
    636 
    637     // 内部class EntryIterator迭代器,我们可以看到修改了next方法
    638     private final class EntryIterator extends HashIterator<Map.Entry<K, V>> {
    639         public Map.Entry<K, V> next() {
    640             return nextEntry();
    641         }
    642     }
    643 
    644     // 定义对应的 iterator() 方法
    645     Iterator<K> newKeyIterator() {
    646         return new KeyIterator();
    647     }
    648 
    649     Iterator<V> newValueIterator() {
    650         return new ValueIterator();
    651     }
    652 
    653     Iterator<Map.Entry<K, V>> newEntryIterator() {
    654         return new EntryIterator();
    655     }
    656 
    657     private transient Set<Map.Entry<K, V>> entrySet = null;
    658 
    659     /**
    660      * 返回此映射中所包含的键的 Set 视图。 该 set 受映射的支持,所以对映射的更改将反映在该 set 中, 反之亦然。如果在对 set
    661      * 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外), 则迭代结果是不确定的。该 set 支持元素的移除,通过
    662      * Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作
    663      * 可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
    664      */
    665     public Set<K> keySet() {
    666         Set<K> ks = keySet();
    667         // 如果keySet为空,则通过新建一个KeySet
    668         return (ks != null ? ks : (ks = new KeySet()));
    669     }
    670 
    671     // 内部类KeySet
    672     private final class KeySet extends AbstractSet<K> {
    673         // 定义iterator方法
    674         public Iterator<K> iterator() {
    675             return newKeyIterator();
    676         }
    677 
    678         // 定义size
    679         public int size() {
    680             return size;
    681         }
    682 
    683         // 定义contains
    684         public boolean contains(Object o) {
    685             return containsKey(o);
    686         }
    687 
    688         // 定义remove
    689         public boolean remove(Object o) {
    690             return HashMap.this.removeEntryForKey(o) != null;
    691         }
    692 
    693         // 定义clear
    694         public void clear() {
    695             HashMap.this.clear();
    696         }
    697     }
    698 
    699     /**
    700      * 返回此映射所包含的值的 Collection 视图。 该 collection 受映射的支持,所以对映射的更改将反映在该 collection
    701      * 中, 反之亦然。如果在对 collection 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外), 则迭代结果是不确定的。该
    702      * collection 支持元素的移除, 通过
    703      * Iterator.remove、Collection.remove、removeAll、retainAll 和 clear 操作
    704      * 可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
    705      */
    706     public Collection<V> values() {
    707         Collection<V> vs = values();
    708         return (vs != null ? vs : (vs = new Values()));
    709     }
    710 
    711     // 内部类Values
    712     private final class Values extends AbstractCollection<V> {
    713         public Iterator<V> iterator() {
    714             return newValueIterator();
    715         }
    716 
    717         public int size() {
    718             return size;
    719         }
    720 
    721         public boolean contains(Object o) {
    722             return containsValue(o);
    723         }
    724 
    725         public void clear() {
    726             HashMap.this.clear();
    727         }
    728     }
    729 
    730     /**
    731      * 返回此映射所包含的映射关系的 Set 视图。 该 set 受映射支持,所以对映射的更改将反映在此 set 中, 反之亦然。如果在对 set
    732      * 进行迭代的同时修改了映射 (通过迭代器自己的 remove 操作,或者通过在该迭代器返回的映射项上执行 setValue 操作除外),
    733      * 则迭代结果是不确定的。该 set 支持元素的移除, 通过
    734      * Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作
    735      * 可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。
    736      */
    737     public Set<Map.Entry<K, V>> entrySet() {
    738         return entrySet0();
    739     }
    740 
    741     private Set<Map.Entry<K, V>> entrySet0() {
    742         Set<Map.Entry<K, V>> es = entrySet;
    743         return es != null ? es : (entrySet = new EntrySet());
    744     }
    745 
    746     // 内部类EntrySet
    747     private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
    748         public Iterator<Map.Entry<K, V>> iterator() {
    749             return newEntryIterator();
    750         }
    751 
    752         public boolean contains(Object o) {
    753             if (!(o instanceof Map.Entry))
    754                 return false;
    755             Map.Entry<K, V> e = (Map.Entry<K, V>) o;
    756             Entry<K, V> candidate = getEntry(e.getKey());
    757             return candidate != null && candidate.equals(e);
    758         }
    759 
    760         public boolean remove(Object o) {
    761             return removeMapping(o) != null;
    762         }
    763 
    764         public int size() {
    765             return size;
    766         }
    767 
    768         public void clear() {
    769             HashMap.this.clear();
    770         }
    771     }
    772 
    773     // 序列化方法
    774     private void writeObject(java.io.ObjectOutputStream s) throws IOException {
    775         Iterator<Map.Entry<K, V>> i = (size > 0) ? entrySet0().iterator() : null;
    776 
    777         s.defaultWriteObject();
    778 
    779         s.writeInt(table.length);
    780 
    781         s.writeInt(size);
    782 
    783         if (i != null) {
    784             while (i.hasNext()) {
    785                 Map.Entry<K, V> e = i.next();
    786                 s.writeObject(e.getKey());
    787                 s.writeObject(e.getValue());
    788             }
    789         }
    790     }
    791 
    792     private static final long serialVersionUID = 362498820763181265L;
    793 
    794     // 通过序列读取对象
    795     private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
    796         s.defaultReadObject();
    797 
    798         int numBuckets = s.readInt();
    799         table = new Entry[numBuckets];
    800 
    801         init();
    802 
    803         int size = s.readInt();
    804 
    805         for (int i = 0; i < size; i++) {
    806             K key = (K) s.readObject();
    807             V value = (V) s.readObject();
    808             putForCreate(key, value);
    809         }
    810     }
    811 
    812     int capacity() {
    813         return table.length;
    814     }
    815 
    816     float loadFactor() {
    817         return loadFactor;
    818     }
    819 }
  • 相关阅读:
    .net软件开发工程师面试题
    html笔记
    好用软件
    谷歌插件
    vue笔记
    js笔记
    数组去重
    css全局样式
    css笔记
    vscod插件
  • 原文地址:https://www.cnblogs.com/midiyu/p/8127506.html
Copyright © 2020-2023  润新知