HashMap源码分析

本文的写作,参考了兰亭风雨的相关博客。

读懂HashMap需要具备一些基础知识

一、基础知识

1、散列

参考【数据结构与算法分析java语言描述】第五章【散列】,

这里我们不讨论具体的哈希的原理。

     1)散列表数据结构只不过是一个包含项(item)的具有固定大小的数组。

     2)散列数组中,每一个项,叫做一个“桶”,英文bucket,它的下标叫bucketIndex。HashMap的结构如下,

HashMap就是一个散列结构,具体到它的内部,就是名为table的Entry数组,代表这个HashMap。table的下标,是每一个Entry的key的hash值与table的length做“与运算”得到的int值(这个功能是indexFor()实现的)。

2、链表

HashMap中的Entry<K,V>,是一个静态内部类,它是一个链表结构;每一个Entry保存自身的key,value,hashCode,以及指向下一个的Entry。

二、indexFor函数的说明:

indexFor函数,参数h代表,hashMap每次put的时候的key的hash值,length代码hashMap当前的大小。

indexFor作用是根据当前key的hash来确定,这一个放入HashMap数组中的Entry应该出于数组的哪一个位置(index)中?

1     static int indexFor(int h, int length) {
2         // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
3         return h & (length-1);
4     }

必要条件是,这个位置bucketIndex肯定不能超过数组大小。于是,最容易的方法是肯定取模。即int bucketIndex = hashNumber % length;然而这个方法效率不高。

另一种方法:

任意正整数a,除以2^n,所得余数c,有如下公式 a = c + k * 2^n(即 被除数= 余数 + 商*除数,这里除数2^n)

把a转换为二进制数,如下,

当除数是2^n,将被除数a的二进制数,右移n位,得到的数就是商,而被移除掉的数字就是余数。

也就是说我们只要得到上图红线右侧的内容就是余数,那么只要将原数字a & (2^n - 1)就可以。

即indexFor()中的

return h & (length-1);

Integer.bitCount(int param),获取param的二进制数中1的个数。

Integer.highestOneBit(int param),获取param的二进制数中,最左侧第一个1,所代表的int值。也就是不大于当前param的最大的2的n次方。

以下是全部代码分析,必要的地方做了注释,

  1 package java.util;
  2 import java.io.*;
  3 
  4 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable{
  5 
  6     static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
  7 
  8     static final int MAXIMUM_CAPACITY = 1 << 30;
  9     static final float DEFAULT_LOAD_FACTOR = 0.75f;
 10     // 空Entry数组
 11     static final Entry<?,?>[] EMPTY_TABLE = {};
 12     // 初始化table
 13     transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
 14     // 保存的Entry数量
 15     transient int size;
 16     // 当threshold大于size(Entry的数量)时,调用resize,
 17     int threshold;
 18 
 19     final float loadFactor;
 20     // 修改次数
 21     transient int modCount;
 22 
 23     static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
 24     private static class Holder {
 25         static final int ALTERNATIVE_HASHING_THRESHOLD;
 26 
 27         static {
 28             String altThreshold = java.security.AccessController.doPrivileged(
 29                 new sun.security.action.GetPropertyAction(
 30                     "jdk.map.althashing.threshold"));
 31 
 32             int threshold;
 33             try {
 34                 threshold = (null != altThreshold)
 35                         ? Integer.parseInt(altThreshold)
 36                         : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;
 37 
 38                 // disable alternative hashing if -1
 39                 if (threshold == -1) {
 40                     threshold = Integer.MAX_VALUE;
 41                 }
 42 
 43                 if (threshold < 0) {
 44                     throw new IllegalArgumentException("value must be positive integer.");
 45                 }
 46             } catch(IllegalArgumentException failed) {
 47                 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
 48             }
 49 
 50             ALTERNATIVE_HASHING_THRESHOLD = threshold;
 51         }
 52     }
 53 
 54     transient int hashSeed = 0;
 55 
 56     // HashMap初始化,table仍然是EMPTY_TABLE,即空Entry数组
 57     // threshold赋值为initialCapacity,默认情况这个值是16
 58     public HashMap(int initialCapacity, float loadFactor) {
 59         if (initialCapacity < 0)
 60             throw new IllegalArgumentException("Illegal initial capacity: " +
 61                                                initialCapacity);
 62         if (initialCapacity > MAXIMUM_CAPACITY)
 63             initialCapacity = MAXIMUM_CAPACITY;
 64         if (loadFactor <= 0 || Float.isNaN(loadFactor))
 65             throw new IllegalArgumentException("Illegal load factor: " +
 66                                                loadFactor);
 67 
 68         this.loadFactor = loadFactor;
 69         threshold = initialCapacity;
 70         init();
 71     }
 72 
 73     public HashMap(int initialCapacity) {
 74         this(initialCapacity, DEFAULT_LOAD_FACTOR);
 75     }
 76 
 77     public HashMap() {
 78         this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
 79     }
 80 
 81     public HashMap(Map<? extends K, ? extends V> m) {
 82         this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
 83                       DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
 84         inflateTable(threshold);
 85 
 86         putAllForCreate(m);
 87     }
 88 
 89     // 取得当前大于number的最小的2的n次方
 90     // number >= MAXIMUM_CAPACITY            = MAXIMUM_CAPACITY
 91     // number <= 1                           = 1
 92     // 1 < number < MAXIMUM_CAPACITY         = 大于当前number的最小的2的n次方
 93     private static int roundUpToPowerOf2(int number) {
 94         // assert number >= 0 : "number must be non-negative";
 95         int rounded = number >= MAXIMUM_CAPACITY
 96                 ? MAXIMUM_CAPACITY
 97                 : (rounded = Integer.highestOneBit(number)) != 0
 98                     ? (Integer.bitCount(number) > 1) ? rounded << 1 : rounded
 99                     : 1;
100 
101         return rounded;
102     }
103     
104     //上面版本不太好阅读,翻译成以下版本。
105     private static int roundUpToPowerOf2(int number){
106         int rounded;
107         if(number >= MAXIMUM_CAPACITY){
108             rounded = MAXIMUM_CAPACITY;
109         }else{
110             //Integer.highestOneBit,取大于number的最小的2的幂。
111             if( (rounded = Integer.highestOneBit(number)) != 0){//如果number不为0
112                 if(Integer.bitCount(number) > 1){//如果number>1
113                     //注意,此时rounded已经是大于number的最小的2的幂。
114                     rounded = rounded << 1;      //将上述rounded左移一位,即乘以2。
115                 }else{
116                     rounded = rounded;
117                 }
118             }else{//如果number为0
119                 rounded = 1;
120             }
121         }
122         return rounded;
123     }
124 
125 
126     // 1、将table变量指向一个新Entry数组,数组length为大于参数的最小2的n次方
127     // 2、修改threshold,为 数组大小* loadFactor
128     // 3、修正hashSeed
129     private void inflateTable(int toSize) {
130         // Find a power of 2 >= toSize
131         int capacity = roundUpToPowerOf2(toSize);
132 
133         threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
134         table = new Entry[capacity];
135         initHashSeedAsNeeded(capacity);
136     }
137 
138     void init() {
139     }
140     // initHashSeedAsNeeded,1:修正hashSeed;2:返回boolean
141     final boolean initHashSeedAsNeeded(int capacity) {
142         boolean currentAltHashing = hashSeed != 0;
143         boolean useAltHashing = sun.misc.VM.isBooted() &&
144                 (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
145         boolean switching = currentAltHashing ^ useAltHashing;
146         if (switching) {
147             hashSeed = useAltHashing
148                 ? sun.misc.Hashing.randomHashSeed(this)
149                 : 0;
150         }
151         return switching;
152     }
153 
154     final int hash(Object k) {
155         int h = hashSeed;
156         if (0 != h && k instanceof String) {
157             return sun.misc.Hashing.stringHash32((String) k);
158         }
159 
160         h ^= k.hashCode();
161 
162         h ^= (h >>> 20) ^ (h >>> 12);
163         return h ^ (h >>> 7) ^ (h >>> 4);
164     }
165     // 将key的hash值与table的length做与运算,得到的int值即为该key在Entry数组中的位置,即bucketIndex。
166     static int indexFor(int h, int length) {
167         // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
168         return h & (length-1);
169     }
170 
171     public int size() {
172         return size;
173     }
174 
175     public boolean isEmpty() {
176         return size == 0;
177     }
178 
179     public V get(Object key) {
180         if (key == null)
181             return getForNullKey();
182         Entry<K,V> entry = getEntry(key);
183 
184         return null == entry ? null : entry.getValue();
185     }
186 
187     private V getForNullKey() {
188         if (size == 0) {
189             return null;
190         }
191         for (Entry<K,V> e = table[0]; e != null; e = e.next) {
192             if (e.key == null)
193                 return e.value;
194         }
195         return null;
196     }
197 
198     public boolean containsKey(Object key) {
199         return getEntry(key) != null;
200     }
201     
202     // 1、根据key值获取hash值
203     // 2、在Entry数组中找到指定的bucket,取出其中的Entry(链表),
204     // 3、遍历这个Entry,如果Entry链表中存在一个Entry的key与传入的key相同,则返回这个Entry
205     final Entry<K,V> getEntry(Object key) {
206         if (size == 0) {
207             return null;
208         }
209 
210         int hash = (key == null) ? 0 : hash(key);
211         for (Entry<K,V> e = table[indexFor(hash, table.length)];
212              e != null;
213              e = e.next) {
214             Object k;
215             if (e.hash == hash &&
216                 ((k = e.key) == key || (key != null && key.equals(k))))
217                 return e;
218         }
219         return null;
220     }
221 
222     // 1、判断table是否为null,若是则调用inflateTable(),参数threshold的值为16(在构造函数中赋值),
223     //    调用roundUpToPowerOf2(大于当前数值的最小的2的n次方)确定capacity,然后new一个Entry数组
224     //    调整threshold的值,调整hashseed
225     // 2、计算key的hash值,调用indexFor确定此key在Entry数组中的bucketIndex
226     // 3、取出Entry数组中的第一个Entry(链表),遍历这个链表,
227     //    3.1、若存在一个Entry的key等于当前key则把这个Entry的value修改,并把old value返回出去,put函数终止
228     //    3.2、若不存在,modCount++,调用addEntry
229     //       3.2.1、判断size是否大于threshold,若是则调用resize(),
230     //       3.2.2、调用createEntry(),先根据bucketIndex取出Entry数组中的Entry(可能为null)
231     //              然后new一个Entry,并把刚取出的Entry作为新Entry的next,
232     //              size++(Entry的数量)
233     public V put(K key, V value) {
234         if (table == EMPTY_TABLE) {
235             inflateTable(threshold);
236         }
237         if (key == null)
238             return putForNullKey(value);
239         int hash = hash(key);
240         int i = indexFor(hash, table.length);
241         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
242             Object k;
243             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
244                 V oldValue = e.value;
245                 e.value = value;
246                 e.recordAccess(this);
247                 return oldValue;
248             }
249         }
250 
251         modCount++;
252         addEntry(hash, key, value, i);
253         return null;
254     }
255 
256     private V putForNullKey(V value) {
257         for (Entry<K,V> e = table[0]; e != null; e = e.next) {
258             if (e.key == null) {
259                 V oldValue = e.value;
260                 e.value = value;
261                 e.recordAccess(this);
262                 return oldValue;
263             }
264         }
265         modCount++;
266         addEntry(0, null, value, 0);
267         return null;
268     }
269 
270     private void putForCreate(K key, V value) {
271         int hash = null == key ? 0 : hash(key);
272         int i = indexFor(hash, table.length);
273 
274         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
275             Object k;
276             if (e.hash == hash &&
277                 ((k = e.key) == key || (key != null && key.equals(k)))) {
278                 e.value = value;
279                 return;
280             }
281         }
282 
283         createEntry(hash, key, value, i);
284     }
285 
286     private void putAllForCreate(Map<? extends K, ? extends V> m) {
287         for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
288             putForCreate(e.getKey(), e.getValue());
289     }
290 
291     // 1、从暴露给外界的函数看,HashMap中调用resize()地方只有两处1:put();2:putAll()
292     //    put()传给resize的参数是Entry数组的length*2;putAll不知道
293     // 2、resize()根据传入的参数newCapacity,new一个新Entry数组,
294     // 3、调用initHashSeedAsNeeded,修正hashSeed,并返回,
295     // 4、调用transfer()将旧Entry数组中的内容全部copy到新Entry数组
296     // 5、调整threshold的值newCapacity * loadFactor
297     void resize(int newCapacity) {
298         Entry[] oldTable = table;
299         int oldCapacity = oldTable.length;
300         if (oldCapacity == MAXIMUM_CAPACITY) {
301             threshold = Integer.MAX_VALUE;
302             return;
303         }
304 
305         Entry[] newTable = new Entry[newCapacity];
306         transfer(newTable, initHashSeedAsNeeded(newCapacity));
307         table = newTable;
308         threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
309     }
310 
311     void transfer(Entry[] newTable, boolean rehash) {
312         int newCapacity = newTable.length;
313         for (Entry<K,V> e : table) {
314             while(null != e) {
315                 Entry<K,V> next = e.next;
316                 if (rehash) {
317                     e.hash = null == e.key ? 0 : hash(e.key);
318                 }
319                 int i = indexFor(e.hash, newCapacity);
320                 e.next = newTable[i];
321                 newTable[i] = e;
322                 e = next;
323             }
324         }
325     }
326 
327     public void putAll(Map<? extends K, ? extends V> m) {
328         int numKeysToBeAdded = m.size();
329         if (numKeysToBeAdded == 0)
330             return;
331 
332         if (table == EMPTY_TABLE) {
333             inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));
334         }
335 
336         if (numKeysToBeAdded > threshold) {
337             int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
338             if (targetCapacity > MAXIMUM_CAPACITY)
339                 targetCapacity = MAXIMUM_CAPACITY;
340             int newCapacity = table.length;
341             while (newCapacity < targetCapacity)
342                 newCapacity <<= 1;
343             if (newCapacity > table.length)
344                 resize(newCapacity);
345         }
346 
347         for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
348             put(e.getKey(), e.getValue());
349     }
350 
351     public V remove(Object key) {
352         Entry<K,V> e = removeEntryForKey(key);
353         return (e == null ? null : e.value);
354     }
355 
356     final Entry<K,V> removeEntryForKey(Object key) {
357         if (size == 0) {
358             return null;
359         }
360         int hash = (key == null) ? 0 : hash(key);
361         int i = indexFor(hash, table.length);
362         Entry<K,V> prev = table[i];
363         Entry<K,V> e = prev;
364 
365         while (e != null) {
366             Entry<K,V> next = e.next;
367             Object k;
368             if (e.hash == hash &&
369                 ((k = e.key) == key || (key != null && key.equals(k)))) {
370                 modCount++;
371                 size--;
372                 if (prev == e)
373                     table[i] = next;
374                 else
375                     prev.next = next;
376                 e.recordRemoval(this);
377                 return e;
378             }
379             prev = e;
380             e = next;
381         }
382 
383         return e;
384     }
385 
386     final Entry<K,V> removeMapping(Object o) {
387         if (size == 0 || !(o instanceof Map.Entry))
388             return null;
389 
390         Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
391         Object key = entry.getKey();
392         int hash = (key == null) ? 0 : hash(key);
393         int i = indexFor(hash, table.length);
394         Entry<K,V> prev = table[i];
395         Entry<K,V> e = prev;
396 
397         while (e != null) {
398             Entry<K,V> next = e.next;
399             if (e.hash == hash && e.equals(entry)) {
400                 modCount++;
401                 size--;
402                 if (prev == e)
403                     table[i] = next;
404                 else
405                     prev.next = next;
406                 e.recordRemoval(this);
407                 return e;
408             }
409             prev = e;
410             e = next;
411         }
412 
413         return e;
414     }
415 
416     public void clear() {
417         modCount++;
418         Arrays.fill(table, null);
419         size = 0;
420     }
421 
422     public boolean containsValue(Object value) {
423         if (value == null)
424             return containsNullValue();
425 
426         Entry[] tab = table;
427         for (int i = 0; i < tab.length ; i++)
428             for (Entry e = tab[i] ; e != null ; e = e.next)
429                 if (value.equals(e.value))
430                     return true;
431         return false;
432     }
433 
434     private boolean containsNullValue() {
435         Entry[] tab = table;
436         for (int i = 0; i < tab.length ; i++)
437             for (Entry e = tab[i] ; e != null ; e = e.next)
438                 if (e.value == null)
439                     return true;
440         return false;
441     }
442 
443     public Object clone() {
444         HashMap<K,V> result = null;
445         try {
446             result = (HashMap<K,V>)super.clone();
447         } catch (CloneNotSupportedException e) {
448             // assert false;
449         }
450         if (result.table != EMPTY_TABLE) {
451             result.inflateTable(Math.min(
452                 (int) Math.min(
453                     size * Math.min(1 / loadFactor, 4.0f),
454                     // we have limits...
455                     HashMap.MAXIMUM_CAPACITY),
456                table.length));
457         }
458         result.entrySet = null;
459         result.modCount = 0;
460         result.size = 0;
461         result.init();
462         result.putAllForCreate(this);
463 
464         return result;
465     }
466 
467     static class Entry<K,V> implements Map.Entry<K,V> {
468         final K key;
469         V value;
470         Entry<K,V> next;
471         int hash;
472 
473         /**
474          * Creates new entry.
475          */
476         Entry(int h, K k, V v, Entry<K,V> n) {
477             value = v;
478             next = n;
479             key = k;
480             hash = h;
481         }
482 
483         public final K getKey() {
484             return key;
485         }
486 
487         public final V getValue() {
488             return value;
489         }
490 
491         public final V setValue(V newValue) {
492             V oldValue = value;
493             value = newValue;
494             return oldValue;
495         }
496 
497         public final boolean equals(Object o) {
498             if (!(o instanceof Map.Entry))
499                 return false;
500             Map.Entry e = (Map.Entry)o;
501             Object k1 = getKey();
502             Object k2 = e.getKey();
503             if (k1 == k2 || (k1 != null && k1.equals(k2))) {
504                 Object v1 = getValue();
505                 Object v2 = e.getValue();
506                 if (v1 == v2 || (v1 != null && v1.equals(v2)))
507                     return true;
508             }
509             return false;
510         }
511 
512         public final int hashCode() {
513             return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
514         }
515 
516         public final String toString() {
517             return getKey() + "=" + getValue();
518         }
519 
520         void recordAccess(HashMap<K,V> m) {
521         }
522 
523         void recordRemoval(HashMap<K,V> m) {
524         }
525     }
526 
527     void addEntry(int hash, K key, V value, int bucketIndex) {
528         if ((size >= threshold) && (null != table[bucketIndex])) {
529             resize(2 * table.length);
530             hash = (null != key) ? hash(key) : 0;
531             bucketIndex = indexFor(hash, table.length);
532         }
533 
534         createEntry(hash, key, value, bucketIndex);
535     }
536 
537 
538     void createEntry(int hash, K key, V value, int bucketIndex) {
539         Entry<K,V> e = table[bucketIndex];
540         table[bucketIndex] = new Entry<>(hash, key, value, e);
541         size++;
542     }
543 
544     private abstract class HashIterator<E> implements Iterator<E> {
545         Entry<K,V> next;        // next entry to return
546         int expectedModCount;   // For fast-fail
547         int index;              // current slot
548         Entry<K,V> current;     // current entry
549 
550         HashIterator() {
551             expectedModCount = modCount;
552             if (size > 0) { // advance to first entry
553                 Entry[] t = table;
554                 while (index < t.length && (next = t[index++]) == null)
555                     ;
556             }
557         }
558 
559         public final boolean hasNext() {
560             return next != null;
561         }
562 
563         final Entry<K,V> nextEntry() {
564             if (modCount != expectedModCount)
565                 throw new ConcurrentModificationException();
566             Entry<K,V> e = next;
567             if (e == null)
568                 throw new NoSuchElementException();
569 
570             if ((next = e.next) == null) {
571                 Entry[] t = table;
572                 while (index < t.length && (next = t[index++]) == null)
573                     ;
574             }
575             current = e;
576             return e;
577         }
578 
579         public void remove() {
580             if (current == null)
581                 throw new IllegalStateException();
582             if (modCount != expectedModCount)
583                 throw new ConcurrentModificationException();
584             Object k = current.key;
585             current = null;
586             HashMap.this.removeEntryForKey(k);
587             expectedModCount = modCount;
588         }
589     }
590 
591     private final class ValueIterator extends HashIterator<V> {
592         public V next() {
593             return nextEntry().value;
594         }
595     }
596 
597     private final class KeyIterator extends HashIterator<K> {
598         public K next() {
599             return nextEntry().getKey();
600         }
601     }
602 
603     private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
604         public Map.Entry<K,V> next() {
605             return nextEntry();
606         }
607     }
608 
609     // Subclass overrides these to alter behavior of views' iterator() method
610     Iterator<K> newKeyIterator()   {
611         return new KeyIterator();
612     }
613     Iterator<V> newValueIterator()   {
614         return new ValueIterator();
615     }
616     Iterator<Map.Entry<K,V>> newEntryIterator()   {
617         return new EntryIterator();
618     }
619 
620 
621     // Views
622 
623     private transient Set<Map.Entry<K,V>> entrySet = null;
624 
625     public Set<K> keySet() {
626         Set<K> ks = keySet;
627         return (ks != null ? ks : (keySet = new KeySet()));
628     }
629 
630     private final class KeySet extends AbstractSet<K> {
631         public Iterator<K> iterator() {
632             return newKeyIterator();
633         }
634         public int size() {
635             return size;
636         }
637         public boolean contains(Object o) {
638             return containsKey(o);
639         }
640         public boolean remove(Object o) {
641             return HashMap.this.removeEntryForKey(o) != null;
642         }
643         public void clear() {
644             HashMap.this.clear();
645         }
646     }
647 
648     public Collection<V> values() {
649         Collection<V> vs = values;
650         return (vs != null ? vs : (values = new Values()));
651     }
652 
653     private final class Values extends AbstractCollection<V> {
654         public Iterator<V> iterator() {
655             return newValueIterator();
656         }
657         public int size() {
658             return size;
659         }
660         public boolean contains(Object o) {
661             return containsValue(o);
662         }
663         public void clear() {
664             HashMap.this.clear();
665         }
666     }
667 
668     public Set<Map.Entry<K,V>> entrySet() {
669         return entrySet0();
670     }
671 
672     private Set<Map.Entry<K,V>> entrySet0() {
673         Set<Map.Entry<K,V>> es = entrySet;
674         return es != null ? es : (entrySet = new EntrySet());
675     }
676 
677     private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
678         public Iterator<Map.Entry<K,V>> iterator() {
679             return newEntryIterator();
680         }
681         public boolean contains(Object o) {
682             if (!(o instanceof Map.Entry))
683                 return false;
684             Map.Entry<K,V> e = (Map.Entry<K,V>) o;
685             Entry<K,V> candidate = getEntry(e.getKey());
686             return candidate != null && candidate.equals(e);
687         }
688         public boolean remove(Object o) {
689             return removeMapping(o) != null;
690         }
691         public int size() {
692             return size;
693         }
694         public void clear() {
695             HashMap.this.clear();
696         }
697     }
698 
699     private void writeObject(java.io.ObjectOutputStream s)
700         throws IOException
701     {
702         // Write out the threshold, loadfactor, and any hidden stuff
703         s.defaultWriteObject();
704 
705         // Write out number of buckets
706         if (table==EMPTY_TABLE) {
707             s.writeInt(roundUpToPowerOf2(threshold));
708         } else {
709            s.writeInt(table.length);
710         }
711 
712         // Write out size (number of Mappings)
713         s.writeInt(size);
714 
715         // Write out keys and values (alternating)
716         if (size > 0) {
717             for(Map.Entry<K,V> e : entrySet0()) {
718                 s.writeObject(e.getKey());
719                 s.writeObject(e.getValue());
720             }
721         }
722     }
723 
724     private static final long serialVersionUID = 362498820763181265L;
725 
726     private void readObject(java.io.ObjectInputStream s)
727          throws IOException, ClassNotFoundException
728     {
729         // Read in the threshold (ignored), loadfactor, and any hidden stuff
730         s.defaultReadObject();
731         if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
732             throw new InvalidObjectException("Illegal load factor: " +
733                                                loadFactor);
734         }
735 
736         // set other fields that need values
737         table = (Entry<K,V>[]) EMPTY_TABLE;
738 
739         // Read in number of buckets
740         s.readInt(); // ignored.
741 
742         // Read number of mappings
743         int mappings = s.readInt();
744         if (mappings < 0)
745             throw new InvalidObjectException("Illegal mappings count: " +
746                                                mappings);
747 
748         // capacity chosen by number of mappings and desired load (if >= 0.25)
749         int capacity = (int) Math.min(
750                     mappings * Math.min(1 / loadFactor, 4.0f),
751                     // we have limits...
752                     HashMap.MAXIMUM_CAPACITY);
753 
754         // allocate the bucket array;
755         if (mappings > 0) {
756             inflateTable(capacity);
757         } else {
758             threshold = capacity;
759         }
760 
761         init();  // Give subclass a chance to do its thing.
762 
763         // Read the keys and values, and put the mappings in the HashMap
764         for (int i = 0; i < mappings; i++) {
765             K key = (K) s.readObject();
766             V value = (V) s.readObject();
767             putForCreate(key, value);
768         }
769     }
770 
771     // These methods are used when serializing HashSets
772     int   capacity()     { return table.length; }
773     float loadFactor()   { return loadFactor;   }
774 }

 

posted @ 2018-09-12 15:53  leondryu  阅读(156)  评论(0)    收藏  举报