轉載地址:http://blog.csdn.net/wangxiaotongfan/article/details/51335368
這一章,我們對HashMap進行學習。
我們先對HashMap有個整體認識,然後再學習它的源碼,最後再通過實例來學會使用HashMap。內容包括:
第1部分 HashMap介紹
第2部分 HashMap數據結構
第3部分 HashMap源碼解析(基於JDK1.6.0_45)
第3.1部分 HashMap的“拉鍊法”相關內容
第3.2部分 HashMap的構造函數
第3.3部分 HashMap的主要對外接口
第3.4部分 HashMap實現的Cloneable接口
第3.5部分 HashMap實現的Serializable接口
第4部分 HashMap遍歷方式
第5部分 HashMap示例
HashMap 是一個散列表,它存儲的內容是鍵值對(key-value)映射。
HashMap 繼承於AbstractMap,實現了Map、Cloneable、java.io.Serializable接口。
HashMap 的實現不是同步的,這意味着它不是線程安全的。它的key、value都可以爲null。此外,HashMap中的映射不是有序的。
HashMap 的實例有兩個參數影響其性能:“初始容量” 和 “加載因子”。
容量是哈希表中桶的數量,初始容量只是哈希表在創建時的容量。加載因子是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行 rehash 操作(即重建內部數據結構),從而哈希表將具有大約兩倍的桶數。
通常,默認加載因子是 0.75, 這是在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查詢成本(在大多數 HashMap 類的操作中,包括 get 和 put 操作,都反映了這一點)。在設置初始容量時應該考慮到映射中所需的條目數及其加載因子,以便最大限度地減少 rehash 操作次數。如果初始容量大於最大條目數除以加載因子,則不會發生 rehash 操作。
HashMap共有4個構造函數,如下:
HashMap()
HashMap(int capacity)
HashMap(int capacity, float loadFactor)
HashMap(Map<? extends K, ? extends V> map)
void clear()
Object clone()
boolean containsKey(Object key)
boolean containsValue(Object value)
Set<Entry<K, V>> entrySet()
V get(Object key)
boolean isEmpty()
Set<K> keySet()
V put(K key, V value)
void putAll(Map<? extends K, ? extends V> map)
V remove(Object key)
int size()
Collection<V> values()
HashMap的繼承關係
java.lang.Object
↳ java.util.AbstractMap<K, V>
↳ java.util.HashMap<K, V>
public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable { }
HashMap與Map關係如下圖:
從圖中可以看出:
(01) HashMap繼承於AbstractMap類,實現了Map接口。Map是”key-value鍵值對”接口,AbstractMap實現了”鍵值對”的通用函數接口。
(02) HashMap是通過“拉鍊法”實現的哈希表。它包括幾個重要的成員變量:table, size, threshold, loadFactor, modCount。
table是一個Entry[]數組類型,而Entry實際上就是一個單向鏈表。哈希表的”key-value鍵值對”都是存儲在Entry數組中的。
size是HashMap的大小,它是HashMap保存的鍵值對的數量。
threshold是HashMap的閾值,用於判斷是否需要調整HashMap的容量。threshold的值=”容量*加載因子”,當HashMap中存儲數據的數量達到threshold時,就需要將HashMap的容量加倍。
loadFactor就是加載因子。
modCount是用來實現fail-fast機制的。
第3部分 HashMap源碼解析(基於JDK1.6.0_45) |
爲了更瞭解HashMap的原理,下面對HashMap源碼代碼作出分析。
在閱讀源碼時,建議參考後面的說明來建立對HashMap的整體認識,這樣更容易理解HashMap。
1 package java.util;
2 import java.io.*;
3
4 public class HashMap<K,V>
5 extends AbstractMap<K,V>
6 implements Map<K,V>, Cloneable, Serializable
7 {
8
9
10 static final int DEFAULT_INITIAL_CAPACITY = 16;
11
12
13 static final int MAXIMUM_CAPACITY = 1 << 30;
14
15
16 static final float DEFAULT_LOAD_FACTOR = 0.75f;
17
18
19
20 transient Entry[] table;
21
22
23 transient int size;
24
25
26 int threshold;
27
28
29 final float loadFactor;
30
31
32 transient volatile int modCount;
33
34
35 public HashMap(int initialCapacity, float loadFactor) {
36 if (initialCapacity < 0)
37 throw new IllegalArgumentException("Illegal initial capacity: " +
38 initialCapacity);
39
40 if (initialCapacity > MAXIMUM_CAPACITY)
41 initialCapacity = MAXIMUM_CAPACITY;
42 if (loadFactor <= 0 || Float.isNaN(loadFactor))
43 throw new IllegalArgumentException("Illegal load factor: " +
44 loadFactor);
45
46
47 int capacity = 1;
48 while (capacity < initialCapacity)
49 capacity <<= 1;
50
51
52 this.loadFactor = loadFactor;
53
54 threshold = (int)(capacity * loadFactor);
55
56 table = new Entry[capacity];
57 init();
58 }
59
60
61
62 public HashMap(int initialCapacity) {
63 this(initialCapacity, DEFAULT_LOAD_FACTOR);
64 }
65
66
67 public HashMap() {
68
69 this.loadFactor = DEFAULT_LOAD_FACTOR;
70
71 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
72
73 table = new Entry[DEFAULT_INITIAL_CAPACITY];
74 init();
75 }
76
77
78 public HashMap(Map<? extends K, ? extends V> m) {
79 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
80 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
81
82 putAllForCreate(m);
83 }
84
85 static int hash(int h) {
86 h ^= (h >>> 20) ^ (h >>> 12);
87 return h ^ (h >>> 7) ^ (h >>> 4);
88 }
89
90
91
92 static int indexFor(int h, int length) {
93 return h & (length-1);
94 }
95
96 public int size() {
97 return size;
98 }
99
100 public boolean isEmpty() {
101 return size == 0;
102 }
103
104
105 public V get(Object key) {
106 if (key == null)
107 return getForNullKey();
108
109 int hash = hash(key.hashCode());
110
111 for (Entry<K,V> e = table[indexFor(hash, table.length)];
112 e != null;
113 e = e.next) {
114 Object k;
115 if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
116 return e.value;
117 }
118 return null;
119 }
120
121
122
123 private V getForNullKey() {
124 for (Entry<K,V> e = table[0]; e != null; e = e.next) {
125 if (e.key == null)
126 return e.value;
127 }
128 return null;
129 }
130
131
132 public boolean containsKey(Object key) {
133 return getEntry(key) != null;
134 }
135
136
137 final Entry<K,V> getEntry(Object key) {
138
139
140 int hash = (key == null) ? 0 : hash(key.hashCode());
141
142 for (Entry<K,V> e = table[indexFor(hash, table.length)];
143 e != null;
144 e = e.next) {
145 Object k;
146 if (e.hash == hash &&
147 ((k = e.key) == key || (key != null && key.equals(k))))
148 return e;
149 }
150 return null;
151 }
152
153
154 public V put(K key, V value) {
155
156 if (key == null)
157 return putForNullKey(value);
158
159 int hash = hash(key.hashCode());
160 int i = indexFor(hash, table.length);
161 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
162 Object k;
163
164 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
165 V oldValue = e.value;
166 e.value = value;
167 e.recordAccess(this);
168 return oldValue;
169 }
170 }
171
172
173 modCount++;
174 addEntry(hash, key, value, i);
175 return null;
176 }
177
178
179 private V putForNullKey(V value) {
180 for (Entry<K,V> e = table[0]; e != null; e = e.next) {
181 if (e.key == null) {
182 V oldValue = e.value;
183 e.value = value;
184 e.recordAccess(this);
185 return oldValue;
186 }
187 }
188
189 modCount++;
190 addEntry(0, null, value, 0);
191 return null;
192 }
193
194
195
196
197 private void putForCreate(K key, V value) {
198 int hash = (key == null) ? 0 : hash(key.hashCode());
199 int i = indexFor(hash, table.length);
200
201
202 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
203 Object k;
204 if (e.hash == hash &&
205 ((k = e.key) == key || (key != null && key.equals(k)))) {
206 e.value = value;
207 return;
208 }
209 }
210
211
212 createEntry(hash, key, value, i);
213 }
214
215
216
217 private void putAllForCreate(Map<? extends K, ? extends V> m) {
218
219 for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
220 Map.Entry<? extends K, ? extends V> e = i.next();
221 putForCreate(e.getKey(), e.getValue());
222 }
223 }
224
225
226 void resize(int newCapacity) {
227 Entry[] oldTable = table;
228 int oldCapacity = oldTable.length;
229 if (oldCapacity == MAXIMUM_CAPACITY) {
230 threshold = Integer.MAX_VALUE;
231 return;
232 }
233
234
235
236 Entry[] newTable = new Entry[newCapacity];
237 transfer(newTable);
238 table = newTable;
239 threshold = (int)(newCapacity * loadFactor);
240 }
241
242
243 void transfer(Entry[] newTable) {
244 Entry[] src = table;
245 int newCapacity = newTable.length;
246 for (int j = 0; j < src.length; j++) {
247 Entry<K,V> e = src[j];
248 if (e != null) {
249 src[j] = null;
250 do {
251 Entry<K,V> next = e.next;
252 int i = indexFor(e.hash, newCapacity);
253 e.next = newTable[i];
254 newTable[i] = e;
255 e = next;
256 } while (e != null);
257 }
258 }
259 }
260
261
262 public void putAll(Map<? extends K, ? extends V> m) {
263
264 int numKeysToBeAdded = m.size();
265 if (numKeysToBeAdded == 0)
266 return;
267
268
269
270 if (numKeysToBeAdded > threshold) {
271 int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
272 if (targetCapacity > MAXIMUM_CAPACITY)
273 targetCapacity = MAXIMUM_CAPACITY;
274 int newCapacity = table.length;
275 while (newCapacity < targetCapacity)
276 newCapacity <<= 1;
277 if (newCapacity > table.length)
278 resize(newCapacity);
279 }
280
281
282 for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
283 Map.Entry<? extends K, ? extends V> e = i.next();
284 put(e.getKey(), e.getValue());
285 }
286 }
287
288
289 public V remove(Object key) {
290 Entry<K,V> e = removeEntryForKey(key);
291 return (e == null ? null : e.value);
292 }
293
294
295 final Entry<K,V> removeEntryForKey(Object key) {
296
297 int hash = (key == null) ? 0 : hash(key.hashCode());
298 int i = indexFor(hash, table.length);
299 Entry<K,V> prev = table[i];
300 Entry<K,V> e = prev;
301
302
303
304 while (e != null) {
305 Entry<K,V> next = e.next;
306 Object k;
307 if (e.hash == hash &&
308 ((k = e.key) == key || (key != null && key.equals(k)))) {
309 modCount++;
310 size--;
311 if (prev == e)
312 table[i] = next;
313 else
314 prev.next = next;
315 e.recordRemoval(this);
316 return e;
317 }
318 prev = e;
319 e = next;
320 }
321
322 return e;
323 }
324
325
326 final Entry<K,V> removeMapping(Object o) {
327 if (!(o instanceof Map.Entry))
328 return null;
329
330 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
331 Object key = entry.getKey();
332 int hash = (key == null) ? 0 : hash(key.hashCode());
333 int i = indexFor(hash, table.length);
334 Entry<K,V> prev = table[i];
335 Entry<K,V> e = prev;
336
337
338
339 while (e != null) {
340 Entry<K,V> next = e.next;
341 if (e.hash == hash && e.equals(entry)) {
342 modCount++;
343 size--;
344 if (prev == e)
345 table[i] = next;
346 else
347 prev.next = next;
348 e.recordRemoval(this);
349 return e;
350 }
351 prev = e;
352 e = next;
353 }
354
355 return e;
356 }
357
358
359 public void clear() {
360 modCount++;
361 Entry[] tab = table;
362 for (int i = 0; i < tab.length; i++)
363 tab[i] = null;
364 size = 0;
365 }
366
367
368 public boolean containsValue(Object value) {
369
370 if (value == null)
371 return containsNullValue();
372
373
374 Entry[] tab = table;
375 for (int i = 0; i < tab.length ; i++)
376 for (Entry e = tab[i] ; e != null ; e = e.next)
377 if (value.equals(e.value))
378 return true;
379 return false;
380 }
381
382
383 private boolean containsNullValue() {
384 Entry[] tab = table;
385 for (int i = 0; i < tab.length ; i++)
386 for (Entry e = tab[i] ; e != null ; e = e.next)
387 if (e.value == null)
388 return true;
389 return false;
390 }
391
392
393 public Object clone() {
394 HashMap<K,V> result = null;
395 try {
396 result = (HashMap<K,V>)super.clone();
397 } catch (CloneNotSupportedException e) {
398
399 }
400 result.table = new Entry[table.length];
401 result.entrySet = null;
402 result.modCount = 0;
403 result.size = 0;
404 result.init();
405
406 result.putAllForCreate(this);
407
408 return result;
409 }
410
411
412
413
414 static class Entry<K,V> implements Map.Entry<K,V> {
415 final K key;
416 V value;
417
418 Entry<K,V> next;
419 final int hash;
420
421
422
423 Entry(int h, K k, V v, Entry<K,V> n) {
424 value = v;
425 next = n;
426 key = k;
427 hash = h;
428 }
429
430 public final K getKey() {
431 return key;
432 }
433
434 public final V getValue() {
435 return value;
436 }
437
438 public final V setValue(V newValue) {
439 V oldValue = value;
440 value = newValue;
441 return oldValue;
442 }
443
444
445
446
447 public final boolean equals(Object o) {
448 if (!(o instanceof Map.Entry))
449 return false;
450 Map.Entry e = (Map.Entry)o;
451 Object k1 = getKey();
452 Object k2 = e.getKey();
453 if (k1 == k2 || (k1 != null && k1.equals(k2))) {
454 Object v1 = getValue();
455 Object v2 = e.getValue();
456 if (v1 == v2 || (v1 != null && v1.equals(v2)))
457 return true;
458 }
459 return false;
460 }
461
462
463 public final int hashCode() {
464 return (key==null ? 0 : key.hashCode()) ^
465 (value==null ? 0 : value.hashCode());
466 }
467
468 public final String toString() {
469 return getKey() + "=" + getValue();
470 }
471
472
473
474 void recordAccess(HashMap<K,V> m) {
475 }
476
477
478
479 void recordRemoval(HashMap<K,V> m) {
480 }
481 }
482
483
484 void addEntry(int hash, K key, V value, int bucketIndex) {
485
486 Entry<K,V> e = table[bucketIndex];
487
488
489 table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
490
491 if (size++ >= threshold)
492 resize(2 * table.length);
493 }
494
495
496
497
498
499
500
501
502
503
504
505
506
507 void createEntry(int hash, K key, V value, int bucketIndex) {
508
509 Entry<K,V> e = table[bucketIndex];
510
511
512 table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
513 size++;
514 }
515
516
517
518 private abstract class HashIterator<E> implements Iterator<E> {
519
520 Entry<K,V> next;
521
522 int expectedModCount;
523
524 int index;
525
526 Entry<K,V> current;
527
528 HashIterator() {
529 expectedModCount = modCount;
530 if (size > 0) {
531 Entry[] t = table;
532
533
534 while (index < t.length && (next = t[index++]) == null)
535 ;
536 }
537 }
538
539 public final boolean hasNext() {
540 return next != null;
541 }
542
543
544 final Entry<K,V> nextEntry() {
545 if (modCount != expectedModCount)
546 throw new ConcurrentModificationException();
547 Entry<K,V> e = next;
548 if (e == null)
549 throw new NoSuchElementException();
550
551
552
553
554
555 if ((next = e.next) == null) {
556 Entry[] t = table;
557 while (index < t.length && (next = t[index++]) == null)
558 ;
559 }
560 current = e;
561 return e;
562 }
563
564
565 public void remove() {
566 if (current == null)
567 throw new IllegalStateException();
568 if (modCount != expectedModCount)
569 throw new ConcurrentModificationException();
570 Object k = current.key;
571 current = null;
572 HashMap.this.removeEntryForKey(k);
573 expectedModCount = modCount;
574 }
575
576 }
577
578
579 private final class ValueIterator extends HashIterator<V> {
580 public V next() {
581 return nextEntry().value;
582 }
583 }
584
585
586 private final class KeyIterator extends HashIterator<K> {
587 public K next() {
588 return nextEntry().getKey();
589 }
590 }
591
592
593 private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
594 public Map.Entry<K,V> next() {
595 return nextEntry();
596 }
597 }
598
599
600 Iterator<K> newKeyIterator() {
601 return new KeyIterator();
602 }
603
604 Iterator<V> newValueIterator() {
605 return new ValueIterator();
606 }
607
608 Iterator<Map.Entry<K,V>> newEntryIterator() {
609 return new EntryIterator();
610 }
611
612
613 private transient Set<Map.Entry<K,V>> entrySet = null;
614
615
616 public Set<K> keySet() {
617 Set<K> ks = keySet;
618 return (ks != null ? ks : (keySet = new KeySet()));
619 }
620
621
622
623 private final class KeySet extends AbstractSet<K> {
624 public Iterator<K> iterator() {
625 return newKeyIterator();
626 }
627 public int size() {
628 return size;
629 }
630 public boolean contains(Object o) {
631 return containsKey(o);
632 }
633 public boolean remove(Object o) {
634 return HashMap.this.removeEntryForKey(o) != null;
635 }
636 public void clear() {
637 HashMap.this.clear();
638 }
639 }
640
641
642 public Collection<V> values() {
643 Collection<V> vs = values;
644 return (vs != null ? vs : (values = new Values()));
645 }
646
647
648
649
650 private final class Values extends AbstractCollection<V> {
651 public Iterator<V> iterator() {
652 return newValueIterator();
653 }
654 public int size() {
655 return size;
656 }
657 public boolean contains(Object o) {
658 return containsValue(o);
659 }
660 public void clear() {
661 HashMap.this.clear();
662 }
663 }
664
665
666 public Set<Map.Entry<K,V>> entrySet() {
667 return entrySet0();
668 }
669
670
671 private Set<Map.Entry<K,V>> entrySet0() {
672 Set<Map.Entry<K,V>> es = entrySet;
673 return es != null ? es : (entrySet = new EntrySet());
674 }
675
676
677
678 private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
679 public Iterator<Map.Entry<K,V>> iterator() {
680 return newEntryIterator();
681 }
682 public boolean contains(Object o) {
683 if (!(o instanceof Map.Entry))
684 return false;
685 Map.Entry<K,V> e = (Map.Entry<K,V>) o;
686 Entry<K,V> candidate = getEntry(e.getKey());
687 return candidate != null && candidate.equals(e);
688 }
689 public boolean remove(Object o) {
690 return removeMapping(o) != null;
691 }
692 public int size() {
693 return size;
694 }
695 public void clear() {
696 HashMap.this.clear();
697 }
698 }
699
700
701
702 private void writeObject(java.io.ObjectOutputStream s)
703 throws IOException
704 {
705 Iterator<Map.Entry<K,V>> i =
706 (size > 0) ? entrySet0().iterator() : null;
707
708
709 s.defaultWriteObject();
710
711
712 s.writeInt(table.length);
713
714
715 s.writeInt(size);
716
717
718 if (i != null) {
719 while (i.hasNext()) {
720 Map.Entry<K,V> e = i.next();
721 s.writeObject(e.getKey());
722 s.writeObject(e.getValue());
723 }
724 }
725 }
726
727
728 private static final long serialVersionUID = 362498820763181265L;
729
730
731
732 private void readObject(java.io.ObjectInputStream s)
733 throws IOException, ClassNotFoundException
734 {
735
736 s.defaultReadObject();
737
738
739 int numBuckets = s.readInt();
740 table = new Entry[numBuckets];
741
742 init();
743
744
745 int size = s.readInt();
746
747
748 for (int i=0; i<size; i++) {
749 K key = (K) s.readObject();
750 V value = (V) s.readObject();
751 putForCreate(key, value);
752 }
753 }
754
755
756 int capacity() { return table.length; }
757
758 float loadFactor() { return loadFactor; }
759 }
- 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
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576
- 577
- 578
- 579
- 580
- 581
- 582
- 583
- 584
- 585
- 586
- 587
- 588
- 589
- 590
- 591
- 592
- 593
- 594
- 595
- 596
- 597
- 598
- 599
- 600
- 601
- 602
- 603
- 604
- 605
- 606
- 607
- 608
- 609
- 610
- 611
- 612
- 613
- 614
- 615
- 616
- 617
- 618
- 619
- 620
- 621
- 622
- 623
- 624
- 625
- 626
- 627
- 628
- 629
- 630
- 631
- 632
- 633
- 634
- 635
- 636
- 637
- 638
- 639
- 640
- 641
- 642
- 643
- 644
- 645
- 646
- 647
- 648
- 649
- 650
- 651
- 652
- 653
- 654
- 655
- 656
- 657
- 658
- 659
- 660
- 661
- 662
- 663
- 664
- 665
- 666
- 667
- 668
- 669
- 670
- 671
- 672
- 673
- 674
- 675
- 676
- 677
- 678
- 679
- 680
- 681
- 682
- 683
- 684
- 685
- 686
- 687
- 688
- 689
- 690
- 691
- 692
- 693
- 694
- 695
- 696
- 697
- 698
- 699
- 700
- 701
- 702
- 703
- 704
- 705
- 706
- 707
- 708
- 709
- 710
- 711
- 712
- 713
- 714
- 715
- 716
- 717
- 718
- 719
- 720
- 721
- 722
- 723
- 724
- 725
- 726
- 727
- 728
- 729
- 730
- 731
- 732
- 733
- 734
- 735
- 736
- 737
- 738
- 739
- 740
- 741
- 742
- 743
- 744
- 745
- 746
- 747
- 748
- 749
- 750
- 751
- 752
- 753
- 754
- 755
- 756
- 757
- 758
- 759
說明:
再次強調
在詳細介紹HashMap的代碼之前,我們需要了解:HashMap就是一個散列表,它是通過“拉鍊法”解決哈希衝突的。
還需要再補充說明的一點是影響HashMap性能的有兩個參數:初始容量(initialCapacity) 和加載因子(loadFactor)。容量 是哈希表中桶的數量,初始容量只是哈希表在創建時的容量。加載因子 是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行 rehash 操作(即重建內部數據結構),從而哈希表將具有大約兩倍的桶數。
transient Entry[] table;
HashMap中的key-value都是存儲在Entry數組中的。
1 static class Entry<K,V> implements Map.Entry<K,V> {
2 final K key;
3 V value;
4
5 Entry<K,V> next;
6 final int hash;
7
8
9
10 Entry(int h, K k, V v, Entry<K,V> n) {
11 value = v;
12 next = n;
13 key = k;
14 hash = h;
15 }
16
17 public final K getKey() {
18 return key;
19 }
20
21 public final V getValue() {
22 return value;
23 }
24
25 public final V setValue(V newValue) {
26 V oldValue = value;
27 value = newValue;
28 return oldValue;
29 }
30
31
32
33
34 public final boolean equals(Object o) {
35 if (!(o instanceof Map.Entry))
36 return false;
37 Map.Entry e = (Map.Entry)o;
38 Object k1 = getKey();
39 Object k2 = e.getKey();
40 if (k1 == k2 || (k1 != null && k1.equals(k2))) {
41 Object v1 = getValue();
42 Object v2 = e.getValue();
43 if (v1 == v2 || (v1 != null && v1.equals(v2)))
44 return true;
45 }
46 return false;
47 }
48
49
50 public final int hashCode() {
51 return (key==null ? 0 : key.hashCode()) ^
52 (value==null ? 0 : value.hashCode());
53 }
54
55 public final String toString() {
56 return getKey() + "=" + getValue();
57 }
58
59
60
61 void recordAccess(HashMap<K,V> m) {
62 }
63
64
65
66 void recordRemoval(HashMap<K,V> m) {
67 }
68 }
- 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
從中,我們可以看出 Entry 實際上就是一個單向鏈表。這也是爲什麼我們說HashMap是通過拉鍊法解決哈希衝突的。
Entry 實現了Map.Entry 接口,即實現getKey(), getValue(), setValue(V value), equals(Object o), hashCode()這些函數。這些都是基本的讀取/修改key、value值的函數。
HashMap共包括4個構造函數
1
2 public HashMap() {
3
4 this.loadFactor = DEFAULT_LOAD_FACTOR;
5
6 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
7
8 table = new Entry[DEFAULT_INITIAL_CAPACITY];
9 init();
10 }
11
12
13 public HashMap(int initialCapacity, float loadFactor) {
14 if (initialCapacity < 0)
15 throw new IllegalArgumentException("Illegal initial capacity: " +
16 initialCapacity);
17
18 if (initialCapacity > MAXIMUM_CAPACITY)
19 initialCapacity = MAXIMUM_CAPACITY;
20 if (loadFactor <= 0 || Float.isNaN(loadFactor))
21 throw new IllegalArgumentException("Illegal load factor: " +
22 loadFactor);
23
24
25 int capacity = 1;
26 while (capacity < initialCapacity)
27 capacity <<= 1;
28
29
30 this.loadFactor = loadFactor;
31
32 threshold = (int)(capacity * loadFactor);
33
34 table = new Entry[capacity];
35 init();
36 }
37
38
39 public HashMap(int initialCapacity) {
40 this(initialCapacity, DEFAULT_LOAD_FACTOR);
41 }
42
43
44 public HashMap(Map<? extends K, ? extends V> m) {
45 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
46 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
47
48 putAllForCreate(m);
49 }
- 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
clear() 的作用是清空HashMap。它是通過將所有的元素設爲null來實現的。
1 public void clear() {
2 modCount++;
3 Entry[] tab = table;
4 for (int i = 0; i < tab.length; i++)
5 tab[i] = null;
6 size = 0;
7 }
containsKey() 的作用是判斷HashMap是否包含key。
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
containsKey() 首先通過getEntry(key)獲取key對應的Entry,然後判斷該Entry是否爲null。
getEntry()的源碼如下:
1 final Entry<K,V> getEntry(Object key) {
2
3
4 int hash = (key == null) ? 0 : hash(key.hashCode());
5
6 for (Entry<K,V> e = table[indexFor(hash, table.length)];
7 e != null;
8 e = e.next) {
9 Object k;
10 if (e.hash == hash &&
11 ((k = e.key) == key || (key != null && key.equals(k))))
12 return e;
13 }
14 return null;
15 }
getEntry() 的作用就是返回“鍵爲key”的鍵值對,它的實現源碼中已經進行了說明。
這裏需要強調的是:HashMap將“key爲null”的元素都放在table的位置0處,即table[0]中;“key不爲null”的放在table的其餘位置!
containsValue() 的作用是判斷HashMap是否包含“值爲value”的元素。
1 public boolean containsValue(Object value) {
2
3 if (value == null)
4 return containsNullValue();
5
6
7 Entry[] tab = table;
8 for (int i = 0; i < tab.length ; i++)
9 for (Entry e = tab[i] ; e != null ; e = e.next)
10 if (value.equals(e.value))
11 return true;
12 return false;
13 }
從中,我們可以看出containsNullValue()分爲兩步進行處理:第一,若“value爲null”,則調用containsNullValue()。第二,若“value不爲null”,則查找HashMap中是否有值爲value的節點。
containsNullValue() 的作用判斷HashMap中是否包含“值爲null”的元素。
1 private boolean containsNullValue() {
2 Entry[] tab = table;
3 for (int i = 0; i < tab.length ; i++)
4 for (Entry e = tab[i] ; e != null ; e = e.next)
5 if (e.value == null)
6 return true;
7 return false;
8 }
3.3.4 entrySet()、values()、keySet() |
它們3個的原理類似,這裏以entrySet()爲例來說明。
entrySet()的作用是返回“HashMap中所有Entry的集合”,它是一個集合。實現代碼如下:
1
2 public Set<Map.Entry<K,V>> entrySet() {
3 return entrySet0();
4 }
5
6
7 private Set<Map.Entry<K,V>> entrySet0() {
8 Set<Map.Entry<K,V>> es = entrySet;
9 return es != null ? es : (entrySet = new EntrySet());
10 }
11
12
13
14 private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
15 public Iterator<Map.Entry<K,V>> iterator() {
16 return newEntryIterator();
17 }
18 public boolean contains(Object o) {
19 if (!(o instanceof Map.Entry))
20 return false;
21 Map.Entry<K,V> e = (Map.Entry<K,V>) o;
22 Entry<K,V> candidate = getEntry(e.getKey());
23 return candidate != null && candidate.equals(e);
24 }
25 public boolean remove(Object o) {
26 return removeMapping(o) != null;
27 }
28 public int size() {
29 return size;
30 }
31 public void clear() {
32 HashMap.this.clear();
33 }
34 }
- 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
HashMap是通過拉鍊法實現的散列表。表現在HashMap包括許多的Entry,而每一個Entry本質上又是一個單向鏈表。那麼HashMap遍歷key-value鍵值對的時候,是如何逐個去遍歷的呢?
下面我們就看看HashMap是如何通過entrySet()遍歷的。
entrySet()實際上是通過newEntryIterator()實現的。 下面我們看看它的代碼:
1
2 Iterator<Map.Entry<K,V>> newEntryIterator() {
3 return new EntryIterator();
4 }
5
6
7 private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
8 public Map.Entry<K,V> next() {
9 return nextEntry();
10 }
11 }
12
13
14
15 private abstract class HashIterator<E> implements Iterator<E> {
16
17 Entry<K,V> next;
18
19 int expectedModCount;
20
21 int index;
22
23 Entry<K,V> current;
24
25 HashIterator() {
26 expectedModCount = modCount;
27 if (size > 0) {
28 Entry[] t = table;
29
30
31 while (index < t.length && (next = t[index++]) == null)
32 ;
33 }
34 }
35
36 public final boolean hasNext() {
37 return next != null;
38 }
39
40
41 final Entry<K,V> nextEntry() {
42 if (modCount != expectedModCount)
43 throw new ConcurrentModificationException();
44 Entry<K,V> e = next;
45 if (e == null)
46 throw new NoSuchElementException();
47
48
49
50
51
52 if ((next = e.next) == null) {
53 Entry[] t = table;
54 while (index < t.length && (next = t[index++]) == null)
55 ;
56 }
57 current = e;
58 return e;
59 }
60
61
62 public void remove() {
63 if (current == null)
64 throw new IllegalStateException();
65 if (modCount != expectedModCount)
66 throw new ConcurrentModificationException();
67 Object k = current.key;
68 current = null;
69 HashMap.this.removeEntryForKey(k);
70 expectedModCount = modCount;
71 }
72
73 }
- 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
當我們通過entrySet()獲取到的Iterator的next()方法去遍歷HashMap時,實際上調用的是 nextEntry() 。而nextEntry()的實現方式,先遍歷Entry(根據Entry在table中的序號,從小到大的遍歷);然後對每個Entry(即每個單向鏈表),逐個遍歷。
get() 的作用是獲取key對應的value,它的實現代碼如下:
1 public V get(Object key) {
2 if (key == null)
3 return getForNullKey();
4
5 int hash = hash(key.hashCode());
6
7 for (Entry<K,V> e = table[indexFor(hash, table.length)];
8 e != null;
9 e = e.next) {
10 Object k;
11 if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
12 return e.value;
13 }
14 return null;
15 }
put() 的作用是對外提供接口,讓HashMap對象可以通過put()將“key-value”添加到HashMap中。
1 public V put(K key, V value) {
2
3 if (key == null)
4 return putForNullKey(value);
5
6 int hash = hash(key.hashCode());
7 int i = indexFor(hash, table.length);
8 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
9 Object k;
10
11 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
12 V oldValue = e.value;
13 e.value = value;
14 e.recordAccess(this);
15 return oldValue;
16 }
17 }
18
19
20 modCount++;
21 addEntry(hash, key, value, i);
22 return null;
23 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
若要添加到HashMap中的鍵值對對應的key已經存在HashMap中,則找到該鍵值對;然後新的value取代舊的value,並退出!
若要添加到HashMap中的鍵值對對應的key不在HashMap中,則將其添加到該哈希值對應的鏈表中,並調用addEntry()。
下面看看addEntry()的代碼:
1 void addEntry(int hash, K key, V value, int bucketIndex) {
2
3 Entry<K,V> e = table[bucketIndex];
4
5
6 table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
7
8 if (size++ >= threshold)
9 resize(2 * table.length);
10 }
addEntry() 的作用是新增Entry。將“key-value”插入指定位置,bucketIndex是位置索引。
說到addEntry(),就不得不說另一個函數createEntry()。createEntry()的代碼如下:
1 void createEntry(int hash, K key, V value, int bucketIndex) {
2
3 Entry<K,V> e = table[bucketIndex];
4
5
6 table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
7 size++;
8 }
它們的作用都是將key、value添加到HashMap中。而且,比較addEntry()和createEntry()的代碼,我們發現addEntry()多了兩句:
if (size++ >= threshold)
resize(2 * table.length);
那它們的區別到底是什麼呢?
閱讀代碼,我們可以發現,它們的使用情景不同。
(01) addEntry()一般用在 新增Entry可能導致“HashMap的實際容量”超過“閾值”的情況下。
例如,我們新建一個HashMap,然後不斷通過put()向HashMap中添加元素;put()是通過addEntry()新增Entry的。
在這種情況下,我們不知道何時“HashMap的實際容量”會超過“閾值”;
因此,需要調用addEntry()
(02) createEntry() 一般用在 新增Entry不會導致“HashMap的實際容量”超過“閾值”的情況下。
例如,我們調用HashMap“帶有Map”的構造函數,它繪將Map的全部元素添加到HashMap中;
但在添加之前,我們已經計算好“HashMap的容量和閾值”。也就是,可以確定“即使將Map中的全部元素添加到HashMap中,都不會超過HashMap的閾值”。
此時,調用createEntry()即可。
putAll() 的作用是將”m”的全部元素都添加到HashMap中,它的代碼如下:
1 public void putAll(Map<? extends K, ? extends V> m) {
2
3 int numKeysToBeAdded = m.size();
4 if (numKeysToBeAdded == 0)
5 return;
6
7
8
9 if (numKeysToBeAdded > threshold) {
10 int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
11 if (targetCapacity > MAXIMUM_CAPACITY)
12 targetCapacity = MAXIMUM_CAPACITY;
13 int newCapacity = table.length;
14 while (newCapacity < targetCapacity)
15 newCapacity <<= 1;
16 if (newCapacity > table.length)
17 resize(newCapacity);
18 }
19
20
21 for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m.entrySet().iterator(); i.hasNext(); ) {
22 Map.Entry<? extends K, ? extends V> e = i.next();
23 put(e.getKey(), e.getValue());
24 }
25 }
- 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
remove() 的作用是刪除“鍵爲key”元素
1 public V remove(Object key) {
2 Entry<K,V> e = removeEntryForKey(key);
3 return (e == null ? null : e.value);
4 }
5
6
7
8 final Entry<K,V> removeEntryForKey(Object key) {
9
10 int hash = (key == null) ? 0 : hash(key.hashCode());
11 int i = indexFor(hash, table.length);
12 Entry<K,V> prev = table[i];
13 Entry<K,V> e = prev;
14
15
16
17 while (e != null) {
18 Entry<K,V> next = e.next;
19 Object k;
20 if (e.hash == hash &&
21 ((k = e.key) == key || (key != null && key.equals(k)))) {
22 modCount++;
23 size--;
24 if (prev == e)
25 table[i] = next;
26 else
27 prev.next = next;
28 e.recordRemoval(this);
29 return e;
30 }
31 prev = e;
32 e = next;
33 }
34
35 return e;
36 }
- 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
第3.4部分 HashMap實現的Cloneable接口 |
HashMap實現了Cloneable接口,即實現了clone()方法。
clone()方法的作用很簡單,就是克隆一個HashMap對象並返回。
1
2 public Object clone() {
3 HashMap<K,V> result = null;
4 try {
5 result = (HashMap<K,V>)super.clone();
6 } catch (CloneNotSupportedException e) {
7
8 }
9 result.table = new Entry[table.length];
10 result.entrySet = null;
11 result.modCount = 0;
12 result.size = 0;
13 result.init();
14
15 result.putAllForCreate(this);
16
17 return result;
18 }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
第3.5部分 HashMap實現的Serializable接口 |
HashMap實現java.io.Serializable,分別實現了串行讀取、寫入功能。
串行寫入函數是writeObject(),它的作用是將HashMap的“總的容量,實際容量,所有的Entry”都寫入到輸出流中。
而串行讀取函數是readObject(),它的作用是將HashMap的“總的容量,實際容量,所有的Entry”依次讀出
1 // java.io.Serializable的寫入函數
2 // 將HashMap的“總的容量,實際容量,所有的Entry”都寫入到輸出流中
3 private void writeObject(java.io.ObjectOutputStream s)
4 throws IOException
5 {
6 Iterator<Map.Entry<K,V>> i =
7 (size > 0) ? entrySet0().iterator() : null
8
9 // Write out the threshold, loadfactor, and any hidden stuff
10 s.defaultWriteObject()
11
12 // Write out number of buckets
13 s.writeInt(table.length)
14
15 // Write out size (number of Mappings)
16 s.writeInt(size)
17
18 // Write out keys and values (alternating)
19 if (i != null) {
20 while (i.hasNext()) {
21 Map.Entry<K,V> e = i.next()
22 s.writeObject(e.getKey())
23 s.writeObject(e.getValue())
24 }
25 }
26 }
27
28 // java.io.Serializable的讀取函數:根據寫入方式讀出
29 // 將HashMap的“總的容量,實際容量,所有的Entry”依次讀出
30 private void readObject(java.io.ObjectInputStream s)
31 throws IOException, ClassNotFoundException
32 {
33 // Read in the threshold, loadfactor, and any hidden stuff
34 s.defaultReadObject()
35
36 // Read in number of buckets and allocate the bucket array
37 int numBuckets = s.readInt()
38 table = new Entry[numBuckets]
39
40 init()
41
42 // Read in size (number of Mappings)
43 int size = s.readInt()
44
45 // Read the keys and values, and put the mappings in the HashMap
46 for (int i=0
47 K key = (K) s.readObject()
48 V value = (V) s.readObject()
49 putForCreate(key, value)
50 }
51 }
- 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
第一步:根據entrySet()獲取HashMap的“鍵值對”的Set集合。
第二步:通過Iterator迭代器遍歷“第一步”得到的集合。
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
key = (String)entry.getKey();
integ = (Integer)entry.getValue();
}
第一步:根據keySet()獲取HashMap的“鍵”的Set集合。
第二步:通過Iterator迭代器遍歷“第一步”得到的集合。
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
key = (String)iter.next();
integ = (Integer)map.get(key);
}
第一步:根據value()獲取HashMap的“值”的集合。
第二步:通過Iterator迭代器遍歷“第一步”得到的集合。
Integer value = null;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
遍歷測試程序如下:
import java.util.Map;
import java.util.Random;
import java.util.Iterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Collection;
public class HashMapIteratorTest {
public static void main(String[] args) {
int val = 0;
String key = null;
Integer value = null;
Random r = new Random();
HashMap map = new HashMap();
for (int i=0; i<12; i++) {
val = r.nextInt(100);
key = String.valueOf(val);
value = r.nextInt(5);
map.put(key, value);
System.out.println(" key:"+key+" value:"+value);
}
iteratorHashMapByEntryset(map) ;
iteratorHashMapByKeyset(map) ;
iteratorHashMapJustValues(map);
}
private static void iteratorHashMapByEntryset(HashMap map) {
if (map == null)
return ;
System.out.println("\niterator HashMap By entryset");
String key = null;
Integer integ = null;
Iterator iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
key = (String)entry.getKey();
integ = (Integer)entry.getValue();
System.out.println(key+" -- "+integ.intValue());
}
}
private static void iteratorHashMapByKeyset(HashMap map) {
if (map == null)
return ;
System.out.println("\niterator HashMap By keyset");
String key = null;
Integer integ = null;
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
key = (String)iter.next();
integ = (Integer)map.get(key);
System.out.println(key+" -- "+integ.intValue());
}
}
private static void iteratorHashMapJustValues(HashMap map) {
if (map == null)
return ;
Collection c = map.values();
Iterator iter= c.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
}
}
}
- 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
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
(自己執行,查看結果吧,就不往出貼結果了)
下面通過一個實例學習如何使用HashMap
1 import java.util.Map
2 import java.util.Random
3 import java.util.Iterator
4 import java.util.HashMap
5 import java.util.HashSet
6 import java.util.Map.Entry
7 import java.util.Collection
8
9
14 public class HashMapTest {
15
16 public static void main(String[] args) {
17 testHashMapAPIs()
18 }
19
20 private static void testHashMapAPIs() {
21 // 初始化隨機種子
22 Random r = new Random()
23 // 新建HashMap
24 HashMap map = new HashMap()
25 // 添加操作
26 map.put("one", r.nextInt(10))
27 map.put("two", r.nextInt(10))
28 map.put("three", r.nextInt(10))
29
30 // 打印出map
31 System.out.println("map:"+map )
32
33 // 通過Iterator遍歷key-value
34 Iterator iter = map.entrySet().iterator()
35 while(iter.hasNext()) {
36 Map.Entry entry = (Map.Entry)iter.next()
37 System.out.println("next : "+ entry.getKey() +" - "+entry.getValue())
38 }
39
40 // HashMap的鍵值對個數
41 System.out.println("size:"+map.size())
42
43 // containsKey(Object key) :是否包含鍵key
44 System.out.println("contains key two : "+map.containsKey("two"))
45 System.out.println("contains key five : "+map.containsKey("five"))
46
47 // containsValue(Object value) :是否包含值value
48 System.out.println("contains value 0 : "+map.containsValue(new Integer(0)))
49
50 // remove(Object key) : 刪除鍵key對應的鍵值對
51 map.remove("three")
52
53 System.out.println("map:"+map )
54
55 // clear() : 清空HashMap
56 map.clear()
57
58 // isEmpty() : HashMap是否爲空
59 System.out.println((map.isEmpty()?"map is empty":"map is not empty") )
60 }
61 }
- 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
(某一次)運行結果:
map:{two=7, one=9, three=6}
next : two - 7
next : one - 9
next : three - 6
size:3
contains key two : true
contains key five : false
contains value 0 : false
map:{two=7, one=9}
map is empty