158 * @serial
159 */
160 int threshold;
161
162 /**
163 * The load factor for the hash table.
164 *
165 * @serial
166 */
167 final float loadFactor;
168
169 /**
170 * The number of times this HashMap has been structurally modified
171 * Structural modifications are those that change the number of mappings in
172 * the HashMap or otherwise modify its internal structure (e.g.,
173 * rehash). This field is used to make iterators on Collection-views of
174 * the HashMap fail-fast. (See ConcurrentModificationException).
175 */
176 transient int modCount;
177
178 /**
179 * Constructs an empty <tt>HashMap</tt> with the specified initial
180 * capacity and load factor.
181 *
182 * @param initialCapacity the initial capacity
183 * @param loadFactor the load factor
184 * @throws IllegalArgumentException if the initial capacity is negative
185 * or the load factor is nonpositive
186 */
187 public HashMap(int initialCapacity, float loadFactor) {
188 if (initialCapacity < 0)
189 throw new IllegalArgumentException("Illegal initial capacity: " +
190 initialCapacity);
191 if (initialCapacity > MAXIMUM_CAPACITY)
192 initialCapacity = MAXIMUM_CAPACITY;
193 if (loadFactor <= 0 || Float.isNaN(loadFactor))
194 throw new IllegalArgumentException("Illegal load factor: " +
195 loadFactor);
196
197 // Find a power of 2 >= initialCapacity
198 int capacity = 1;
199 while (capacity < initialCapacity)
200 capacity <<= 1;
201
202 this.loadFactor = loadFactor;
203 threshold = (int)(capacity * loadFactor);
204 table = new Entry[capacity];
205 init();
206 }
207
208 /**
209 * Constructs an empty <tt>HashMap</tt> with the specified initial
210 * capacity and the default load factor (0.75).
211 *
212 * @param initialCapacity the initial capacity.
213 * @throws IllegalArgumentException if the initial capacity is negative.
214 */
215 public HashMap(int initialCapacity) {
216 this(initialCapacity, DEFAULT_LOAD_FACTOR);
217 }
218
219 /**
220 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
221 * (16) and the default load factor (0.75).
222 */
223 public HashMap() {
224 this.loadFactor = DEFAULT_LOAD_FACTOR;
225 threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
226 table = new Entry[DEFAULT_INITIAL_CAPACITY];
227 init();
228 }
229
230 /**
231 * Constructs a new <tt>HashMap</tt> with the same mappings as the
232 * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with
233 * default load factor (0.75) and an initial capacity sufficient to
234 * hold the mappings in the specified <tt>Map</tt>.
235 *
236 * @param m the map whose mappings are to be placed in this map
237 * @throws NullPointerException if the specified map is null
238 */
239 public HashMap(Map<? extends K, ? extends V> m) {
240 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
241 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
242 putAllForCreate(m);
243 }
244
245 // internal utilities
246
247 /**
248 * Initialization hook for subclasses. This method is called
249 * in all constructors and pseudo-constructors (clone, readObject)
250 * after HashMap has been initialized but before any entries have
251 * been inserted. (In the absence of this method, readObject would
252 * require explicit knowledge of subclasses.)
253 */
254 void init() {
255 }
256
257 /**
258 * Applies a supplemental hash function to a given hashCode, which
259 * defends against poor quality hash functions. This is critical
260 * because HashMap uses power-of-two length hash tables, that
261 * otherwise encounter collisions for hashCodes that do not differ
262 * in lower bits. Note: Null keys always map to hash 0, thus index 0.
263 */
264 static int hash(int h) {
265 // This function ensures that hashCodes that differ only by
266 // constant multiples at each bit position have a bounded
267 // number of collisions (approximately 8 at default load factor).
268 h ^= (h >>> 20) ^ (h >>> 12);
269 return h ^ (h >>> 7) ^ (h >>> 4);
270 }
271
272 /**
273 * Returns index for hash code h.
274 */
275 static int indexFor(int h, int length) {
276 return h & (length-1);
277 }
278
279 /**
280 * Returns the number of key-value mappings in this map.
281 *
282 * @return the number of key-value mappings in this map
283 */
284 public int size() {
296
297 /**
298 * Returns the value to which the specified key is mapped,
299 * or {@code null} if this map contains no mapping for the key.
300 *
301 * <p>More formally, if this map contains a mapping from a key
302 * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
303 * key.equals(k))}, then this method returns {@code v}; otherwise
304 * it returns {@code null}. (There can be at most one such mapping.)
305 *
306 * <p>A return value of {@code null} does not <i>necessarily</i>
307 * indicate that the map contains no mapping for the key; it's also
308 * possible that the map explicitly maps the key to {@code null}.
309 * The {@link #containsKey containsKey} operation may be used to
310 * distinguish these two cases.
311 *
312 * @see #put(Object, Object)
313 */
314 @SuppressWarnings("unchecked")
315 public V get(Object key) {
316 if (key == null)
317 return (V)getForNullKey();
318 int hash = hash(key.hashCode());
319 for (Entry<?,?> e = table[indexFor(hash, table.length)];
320 e != null;
321 e = e.next) {
322 Object k;
323 if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
324 return (V)e.value;
325 }
326 return null;
327 }
328
329 /**
330 * Offloaded version of get() to look up null keys. Null keys map
331 * to index 0. This null case is split out into separate methods
332 * for the sake of performance in the two most commonly used
333 * operations (get and put), but incorporated with conditionals in
334 * others.
335 */
336 private Object getForNullKey() {
337 for (Entry<?,?> e = table[0]; e != null; e = e.next) {
338 if (e.key == null)
339 return e.value;
340 }
341 return null;
342 }
343
344 /**
345 * Returns <tt>true</tt> if this map contains a mapping for the
346 * specified key.
347 *
348 * @param key The key whose presence in this map is to be tested
349 * @return <tt>true</tt> if this map contains a mapping for the specified
350 * key.
351 */
352 public boolean containsKey(Object key) {
353 return getEntry(key) != null;
354 }
355
356 /**
357 * Returns the entry associated with the specified key in the
358 * HashMap. Returns null if the HashMap contains no mapping
359 * for the key.
360 */
361 @SuppressWarnings("unchecked")
362 final Entry<K,V> getEntry(Object key) {
363 int hash = (key == null) ? 0 : hash(key.hashCode());
364 for (Entry<?,?> e = table[indexFor(hash, table.length)];
365 e != null;
366 e = e.next) {
367 Object k;
368 if (e.hash == hash &&
369 ((k = e.key) == key || (key != null && key.equals(k))))
370 return (Entry<K,V>)e;
371 }
372 return null;
373 }
374
375
376 /**
377 * Associates the specified value with the specified key in this map.
378 * If the map previously contained a mapping for the key, the old
379 * value is replaced.
380 *
381 * @param key key with which the specified value is to be associated
382 * @param value value to be associated with the specified key
383 * @return the previous value associated with <tt>key</tt>, or
384 * <tt>null</tt> if there was no mapping for <tt>key</tt>.
385 * (A <tt>null</tt> return can also indicate that the map
386 * previously associated <tt>null</tt> with <tt>key</tt>.)
387 */
388 public V put(K key, V value) {
389 if (key == null)
390 return putForNullKey(value);
391 int hash = hash(key.hashCode());
392 int i = indexFor(hash, table.length);
393 @SuppressWarnings("unchecked")
394 Entry<K,V> e = (Entry<K,V>)table[i];
395 for(; e != null; e = e.next) {
396 Object k;
397 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
398 V oldValue = e.value;
399 e.value = value;
400 e.recordAccess(this);
401 return oldValue;
402 }
403 }
404
405 modCount++;
406 addEntry(hash, key, value, i);
407 return null;
408 }
409
410 /**
411 * Offloaded version of put for null keys
416 for(; e != null; e = e.next) {
417 if (e.key == null) {
418 V oldValue = e.value;
419 e.value = value;
420 e.recordAccess(this);
421 return oldValue;
422 }
423 }
424 modCount++;
425 addEntry(0, null, value, 0);
426 return null;
427 }
428
429 /**
430 * This method is used instead of put by constructors and
431 * pseudoconstructors (clone, readObject). It does not resize the table,
432 * check for comodification, etc. It calls createEntry rather than
433 * addEntry.
434 */
435 private void putForCreate(K key, V value) {
436 int hash = (key == null) ? 0 : hash(key.hashCode());
437 int i = indexFor(hash, table.length);
438
439 /**
440 * Look for preexisting entry for key. This will never happen for
441 * clone or deserialize. It will only happen for construction if the
442 * input Map is a sorted map whose ordering is inconsistent w/ equals.
443 */
444 for (@SuppressWarnings("unchecked")
445 Entry<?,V> e = (Entry<?,V>)table[i]; e != null; e = e.next) {
446 Object k;
447 if (e.hash == hash &&
448 ((k = e.key) == key || (key != null && key.equals(k)))) {
449 e.value = value;
450 return;
451 }
452 }
453
454 createEntry(hash, key, value, i);
455 }
456
467 * If current capacity is MAXIMUM_CAPACITY, this method does not
468 * resize the map, but sets threshold to Integer.MAX_VALUE.
469 * This has the effect of preventing future calls.
470 *
471 * @param newCapacity the new capacity, MUST be a power of two;
472 * must be greater than current capacity unless current
473 * capacity is MAXIMUM_CAPACITY (in which case value
474 * is irrelevant).
475 */
476 void resize(int newCapacity) {
477 Entry<?,?>[] oldTable = table;
478 int oldCapacity = oldTable.length;
479 if (oldCapacity == MAXIMUM_CAPACITY) {
480 threshold = Integer.MAX_VALUE;
481 return;
482 }
483
484 Entry<?,?>[] newTable = new Entry<?,?>[newCapacity];
485 transfer(newTable);
486 table = newTable;
487 threshold = (int)(newCapacity * loadFactor);
488 }
489
490 /**
491 * Transfers all entries from current table to newTable.
492 */
493 @SuppressWarnings("unchecked")
494 void transfer(Entry<?,?>[] newTable) {
495 Entry<?,?>[] src = table;
496 int newCapacity = newTable.length;
497 for (int j = 0; j < src.length; j++) {
498 Entry<K,V> e = (Entry<K,V>)src[j];
499 if (e != null) {
500 src[j] = null;
501 do {
502 Entry<K,V> next = e.next;
503 int i = indexFor(e.hash, newCapacity);
504 e.next = (Entry<K,V>)newTable[i];
505 newTable[i] = e;
506 e = next;
507 } while (e != null);
508 }
509 }
510 }
511
512 /**
513 * Copies all of the mappings from the specified map to this map.
514 * These mappings will replace any mappings that this map had for
515 * any of the keys currently in the specified map.
516 *
517 * @param m mappings to be stored in this map
518 * @throws NullPointerException if the specified map is null
519 */
520 public void putAll(Map<? extends K, ? extends V> m) {
521 int numKeysToBeAdded = m.size();
522 if (numKeysToBeAdded == 0)
523 return;
524
525 /*
526 * Expand the map if the map if the number of mappings to be added
527 * is greater than or equal to threshold. This is conservative; the
528 * obvious condition is (m.size() + size) >= threshold, but this
529 * condition could result in a map with twice the appropriate capacity,
549 /**
550 * Removes the mapping for the specified key from this map if present.
551 *
552 * @param key key whose mapping is to be removed from the map
553 * @return the previous value associated with <tt>key</tt>, or
554 * <tt>null</tt> if there was no mapping for <tt>key</tt>.
555 * (A <tt>null</tt> return can also indicate that the map
556 * previously associated <tt>null</tt> with <tt>key</tt>.)
557 */
558 public V remove(Object key) {
559 Entry<K,V> e = removeEntryForKey(key);
560 return (e == null ? null : e.value);
561 }
562
563 /**
564 * Removes and returns the entry associated with the specified key
565 * in the HashMap. Returns null if the HashMap contains no mapping
566 * for this key.
567 */
568 final Entry<K,V> removeEntryForKey(Object key) {
569 int hash = (key == null) ? 0 : hash(key.hashCode());
570 int i = indexFor(hash, table.length);
571 @SuppressWarnings("unchecked")
572 Entry<K,V> prev = (Entry<K,V>)table[i];
573 Entry<K,V> e = prev;
574
575 while (e != null) {
576 Entry<K,V> next = e.next;
577 Object k;
578 if (e.hash == hash &&
579 ((k = e.key) == key || (key != null && key.equals(k)))) {
580 modCount++;
581 size--;
582 if (prev == e)
583 table[i] = next;
584 else
585 prev.next = next;
586 e.recordRemoval(this);
587 return e;
588 }
589 prev = e;
590 e = next;
591 }
592
593 return e;
594 }
595
596 /**
597 * Special version of remove for EntrySet.
598 */
599 final Entry<K,V> removeMapping(Object o) {
600 if (!(o instanceof Map.Entry))
601 return null;
602
603 Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
604 Object key = entry.getKey();
605 int hash = (key == null) ? 0 : hash(key.hashCode());
606 int i = indexFor(hash, table.length);
607 @SuppressWarnings("unchecked")
608 Entry<K,V> prev = (Entry<K,V>)table[i];
609 Entry<K,V> e = prev;
610
611 while (e != null) {
612 Entry<K,V> next = e.next;
613 if (e.hash == hash && e.equals(entry)) {
614 modCount++;
615 size--;
616 if (prev == e)
617 table[i] = next;
756 */
757 void recordAccess(HashMap<K,V> m) {
758 }
759
760 /**
761 * This method is invoked whenever the entry is
762 * removed from the table.
763 */
764 void recordRemoval(HashMap<K,V> m) {
765 }
766 }
767
768 /**
769 * Adds a new entry with the specified key, value and hash code to
770 * the specified bucket. It is the responsibility of this
771 * method to resize the table if appropriate.
772 *
773 * Subclass overrides this to alter the behavior of put method.
774 */
775 void addEntry(int hash, K key, V value, int bucketIndex) {
776 @SuppressWarnings("unchecked")
777 Entry<K,V> e = (Entry<K,V>)table[bucketIndex];
778 table[bucketIndex] = new Entry<>(hash, key, value, e);
779 if (size++ >= threshold)
780 resize(2 * table.length);
781 }
782
783 /**
784 * Like addEntry except that this version is used when creating entries
785 * as part of Map construction or "pseudo-construction" (cloning,
786 * deserialization). This version needn't worry about resizing the table.
787 *
788 * Subclass overrides this to alter the behavior of HashMap(Map),
789 * clone, and readObject.
790 */
791 void createEntry(int hash, K key, V value, int bucketIndex) {
792 @SuppressWarnings("unchecked")
793 Entry<K,V> e = (Entry<K,V>)table[bucketIndex];
794 table[bucketIndex] = new Entry<>(hash, key, value, e);
795 size++;
796 }
797
798 private abstract class HashIterator<E> implements Iterator<E> {
799 Entry<?,?> next; // next entry to return
800 int expectedModCount; // For fast-fail
824
825 if ((next = e.next) == null) {
826 Entry<?,?>[] t = table;
827 while (index < t.length && (next = t[index++]) == null)
828 ;
829 }
830 current = e;
831 return (Entry<K,V>)e;
832 }
833
834 public void remove() {
835 if (current == null)
836 throw new IllegalStateException();
837 if (modCount != expectedModCount)
838 throw new ConcurrentModificationException();
839 Object k = current.key;
840 current = null;
841 HashMap.this.removeEntryForKey(k);
842 expectedModCount = modCount;
843 }
844
845 }
846
847 private final class ValueIterator extends HashIterator<V> {
848 public V next() {
849 return nextEntry().value;
850 }
851 }
852
853 private final class KeyIterator extends HashIterator<K> {
854 public K next() {
855 return nextEntry().getKey();
856 }
857 }
858
859 private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
860 public Map.Entry<K,V> next() {
861 return nextEntry();
862 }
863 }
864
1004 * mappings), followed by the key (Object) and value (Object)
1005 * for each key-value mapping. The key-value mappings are
1006 * emitted in no particular order.
1007 */
1008 private void writeObject(java.io.ObjectOutputStream s)
1009 throws IOException
1010 {
1011 Iterator<Map.Entry<K,V>> i =
1012 (size > 0) ? entrySet0().iterator() : null;
1013
1014 // Write out the threshold, loadfactor, and any hidden stuff
1015 s.defaultWriteObject();
1016
1017 // Write out number of buckets
1018 s.writeInt(table.length);
1019
1020 // Write out size (number of Mappings)
1021 s.writeInt(size);
1022
1023 // Write out keys and values (alternating)
1024 if (i != null) {
1025 while (i.hasNext()) {
1026 Map.Entry<K,V> e = i.next();
1027 s.writeObject(e.getKey());
1028 s.writeObject(e.getValue());
1029 }
1030 }
1031 }
1032
1033 private static final long serialVersionUID = 362498820763181265L;
1034
1035 /**
1036 * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,
1037 * deserialize it).
1038 */
1039 private void readObject(java.io.ObjectInputStream s)
1040 throws IOException, ClassNotFoundException
1041 {
1042 // Read in the threshold, loadfactor, and any hidden stuff
1043 s.defaultReadObject();
1044
1045 // Read in number of buckets and allocate the bucket array;
1046 int numBuckets = s.readInt();
1047 table = new Entry[numBuckets];
1048
1049 init(); // Give subclass a chance to do its thing.
1050
1051 // Read in size (number of Mappings)
1052 int size = s.readInt();
1053
1054 // Read the keys and values, and put the mappings in the HashMap
1055 for (int i=0; i<size; i++) {
1056 @SuppressWarnings("unchecked")
1057 K key = (K) s.readObject();
1058 @SuppressWarnings("unchecked")
1059 V value = (V) s.readObject();
1060 putForCreate(key, value);
1061 }
1062 }
1063
1064 // These methods are used when serializing HashSets
1065 int capacity() { return table.length; }
1066 float loadFactor() { return loadFactor; }
1067 }
|
158 * @serial
159 */
160 int threshold;
161
162 /**
163 * The load factor for the hash table.
164 *
165 * @serial
166 */
167 final float loadFactor;
168
169 /**
170 * The number of times this HashMap has been structurally modified
171 * Structural modifications are those that change the number of mappings in
172 * the HashMap or otherwise modify its internal structure (e.g.,
173 * rehash). This field is used to make iterators on Collection-views of
174 * the HashMap fail-fast. (See ConcurrentModificationException).
175 */
176 transient int modCount;
177
178 private static class Holder {
179 /**
180 *
181 */
182 static final sun.misc.Unsafe UNSAFE;
183
184 /**
185 * Offset of "final" hashSeed field we must set in
186 * readObject() method.
187 */
188 static final long HASHSEED_OFFSET;
189
190 static {
191 try {
192 UNSAFE = sun.misc.Unsafe.getUnsafe();
193 HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
194 HashMap.class.getDeclaredField("hashSeed"));
195 } catch (NoSuchFieldException | SecurityException e) {
196 throw new InternalError("Failed to record hashSeed offset", e);
197 }
198 }
199 }
200
201 /**
202 * A randomizing value associated with this instance that is applied to
203 * hash code of keys to make hash collisions harder to find.
204 */
205 transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
206
207 /**
208 * Constructs an empty <tt>HashMap</tt> with the specified initial
209 * capacity and load factor.
210 *
211 * @param initialCapacity the initial capacity
212 * @param loadFactor the load factor
213 * @throws IllegalArgumentException if the initial capacity is negative
214 * or the load factor is nonpositive
215 */
216 public HashMap(int initialCapacity, float loadFactor) {
217 if (initialCapacity < 0)
218 throw new IllegalArgumentException("Illegal initial capacity: " +
219 initialCapacity);
220 if (initialCapacity > MAXIMUM_CAPACITY)
221 initialCapacity = MAXIMUM_CAPACITY;
222 if (loadFactor <= 0 || Float.isNaN(loadFactor))
223 throw new IllegalArgumentException("Illegal load factor: " +
224 loadFactor);
225
226 // Find a power of 2 >= initialCapacity
227 int capacity = 1;
228 while (capacity < initialCapacity)
229 capacity <<= 1;
230
231 this.loadFactor = loadFactor;
232 threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
233 table = new Entry[capacity];
234 init();
235 }
236
237 /**
238 * Constructs an empty <tt>HashMap</tt> with the specified initial
239 * capacity and the default load factor (0.75).
240 *
241 * @param initialCapacity the initial capacity.
242 * @throws IllegalArgumentException if the initial capacity is negative.
243 */
244 public HashMap(int initialCapacity) {
245 this(initialCapacity, DEFAULT_LOAD_FACTOR);
246 }
247
248 /**
249 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
250 * (16) and the default load factor (0.75).
251 */
252 public HashMap() {
253 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
254 }
255
256 /**
257 * Constructs a new <tt>HashMap</tt> with the same mappings as the
258 * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with
259 * default load factor (0.75) and an initial capacity sufficient to
260 * hold the mappings in the specified <tt>Map</tt>.
261 *
262 * @param m the map whose mappings are to be placed in this map
263 * @throws NullPointerException if the specified map is null
264 */
265 public HashMap(Map<? extends K, ? extends V> m) {
266 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
267 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
268 putAllForCreate(m);
269 }
270
271 // internal utilities
272
273 /**
274 * Initialization hook for subclasses. This method is called
275 * in all constructors and pseudo-constructors (clone, readObject)
276 * after HashMap has been initialized but before any entries have
277 * been inserted. (In the absence of this method, readObject would
278 * require explicit knowledge of subclasses.)
279 */
280 void init() {
281 }
282
283 /**
284 * Retrieve object hash code and applies a supplemental hash function to the
285 * result hash, which defends against poor quality hash functions. This is
286 * critical because HashMap uses power-of-two length hash tables, that
287 * otherwise encounter collisions for hashCodes that do not differ
288 * in lower bits.
289 */
290 final int hash(Object k) {
291 int h = hashSeed;
292 if (k instanceof String) {
293 return h ^ ((String)k).hash32();
294 }
295
296 h ^= k.hashCode();
297
298 // This function ensures that hashCodes that differ only by
299 // constant multiples at each bit position have a bounded
300 // number of collisions (approximately 8 at default load factor).
301 h ^= (h >>> 20) ^ (h >>> 12);
302 return h ^ (h >>> 7) ^ (h >>> 4);
303 }
304
305 /**
306 * Returns index for hash code h.
307 */
308 static int indexFor(int h, int length) {
309 return h & (length-1);
310 }
311
312 /**
313 * Returns the number of key-value mappings in this map.
314 *
315 * @return the number of key-value mappings in this map
316 */
317 public int size() {
329
330 /**
331 * Returns the value to which the specified key is mapped,
332 * or {@code null} if this map contains no mapping for the key.
333 *
334 * <p>More formally, if this map contains a mapping from a key
335 * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
336 * key.equals(k))}, then this method returns {@code v}; otherwise
337 * it returns {@code null}. (There can be at most one such mapping.)
338 *
339 * <p>A return value of {@code null} does not <i>necessarily</i>
340 * indicate that the map contains no mapping for the key; it's also
341 * possible that the map explicitly maps the key to {@code null}.
342 * The {@link #containsKey containsKey} operation may be used to
343 * distinguish these two cases.
344 *
345 * @see #put(Object, Object)
346 */
347 @SuppressWarnings("unchecked")
348 public V get(Object key) {
349 Entry<K,V> entry = getEntry(key);
350
351 return null == entry ? null : entry.getValue();
352 }
353
354 /**
355 * Returns <tt>true</tt> if this map contains a mapping for the
356 * specified key.
357 *
358 * @param key The key whose presence in this map is to be tested
359 * @return <tt>true</tt> if this map contains a mapping for the specified
360 * key.
361 */
362 public boolean containsKey(Object key) {
363 return getEntry(key) != null;
364 }
365
366 /**
367 * Returns the entry associated with the specified key in the
368 * HashMap. Returns null if the HashMap contains no mapping
369 * for the key.
370 */
371 @SuppressWarnings("unchecked")
372 final Entry<K,V> getEntry(Object key) {
373 int hash = (key == null) ? 0 : hash(key);
374 for (Entry<?,?> e = table[indexFor(hash, table.length)];
375 e != null;
376 e = e.next) {
377 Object k;
378 if (e.hash == hash &&
379 ((k = e.key) == key || (key != null && key.equals(k))))
380 return (Entry<K,V>)e;
381 }
382 return null;
383 }
384
385
386 /**
387 * Associates the specified value with the specified key in this map.
388 * If the map previously contained a mapping for the key, the old
389 * value is replaced.
390 *
391 * @param key key with which the specified value is to be associated
392 * @param value value to be associated with the specified key
393 * @return the previous value associated with <tt>key</tt>, or
394 * <tt>null</tt> if there was no mapping for <tt>key</tt>.
395 * (A <tt>null</tt> return can also indicate that the map
396 * previously associated <tt>null</tt> with <tt>key</tt>.)
397 */
398 public V put(K key, V value) {
399 if (key == null)
400 return putForNullKey(value);
401 int hash = hash(key);
402 int i = indexFor(hash, table.length);
403 @SuppressWarnings("unchecked")
404 Entry<K,V> e = (Entry<K,V>)table[i];
405 for(; e != null; e = e.next) {
406 Object k;
407 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
408 V oldValue = e.value;
409 e.value = value;
410 e.recordAccess(this);
411 return oldValue;
412 }
413 }
414
415 modCount++;
416 addEntry(hash, key, value, i);
417 return null;
418 }
419
420 /**
421 * Offloaded version of put for null keys
426 for(; e != null; e = e.next) {
427 if (e.key == null) {
428 V oldValue = e.value;
429 e.value = value;
430 e.recordAccess(this);
431 return oldValue;
432 }
433 }
434 modCount++;
435 addEntry(0, null, value, 0);
436 return null;
437 }
438
439 /**
440 * This method is used instead of put by constructors and
441 * pseudoconstructors (clone, readObject). It does not resize the table,
442 * check for comodification, etc. It calls createEntry rather than
443 * addEntry.
444 */
445 private void putForCreate(K key, V value) {
446 int hash = null == key ? 0 : hash(key);
447 int i = indexFor(hash, table.length);
448
449 /**
450 * Look for preexisting entry for key. This will never happen for
451 * clone or deserialize. It will only happen for construction if the
452 * input Map is a sorted map whose ordering is inconsistent w/ equals.
453 */
454 for (@SuppressWarnings("unchecked")
455 Entry<?,V> e = (Entry<?,V>)table[i]; e != null; e = e.next) {
456 Object k;
457 if (e.hash == hash &&
458 ((k = e.key) == key || (key != null && key.equals(k)))) {
459 e.value = value;
460 return;
461 }
462 }
463
464 createEntry(hash, key, value, i);
465 }
466
477 * If current capacity is MAXIMUM_CAPACITY, this method does not
478 * resize the map, but sets threshold to Integer.MAX_VALUE.
479 * This has the effect of preventing future calls.
480 *
481 * @param newCapacity the new capacity, MUST be a power of two;
482 * must be greater than current capacity unless current
483 * capacity is MAXIMUM_CAPACITY (in which case value
484 * is irrelevant).
485 */
486 void resize(int newCapacity) {
487 Entry<?,?>[] oldTable = table;
488 int oldCapacity = oldTable.length;
489 if (oldCapacity == MAXIMUM_CAPACITY) {
490 threshold = Integer.MAX_VALUE;
491 return;
492 }
493
494 Entry<?,?>[] newTable = new Entry<?,?>[newCapacity];
495 transfer(newTable);
496 table = newTable;
497 threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
498 }
499
500 /**
501 * Transfers all entries from current table to newTable.
502 */
503 @SuppressWarnings("unchecked")
504 void transfer(Entry<?,?>[] newTable) {
505 Entry<?,?>[] src = table;
506 int newCapacity = newTable.length;
507 for (int j = 0; j < src.length; j++ ) {
508 Entry<K,V> e = (Entry<K,V>) src[j];
509 while(null != e) {
510 Entry<K,V> next = e.next;
511 int i = indexFor(e.hash, newCapacity);
512 e.next = (Entry<K,V>) newTable[i];
513 newTable[i] = e;
514 e = next;
515 }
516 }
517 Arrays.fill(table, null);
518 }
519
520 /**
521 * Copies all of the mappings from the specified map to this map.
522 * These mappings will replace any mappings that this map had for
523 * any of the keys currently in the specified map.
524 *
525 * @param m mappings to be stored in this map
526 * @throws NullPointerException if the specified map is null
527 */
528 public void putAll(Map<? extends K, ? extends V> m) {
529 int numKeysToBeAdded = m.size();
530 if (numKeysToBeAdded == 0)
531 return;
532
533 /*
534 * Expand the map if the map if the number of mappings to be added
535 * is greater than or equal to threshold. This is conservative; the
536 * obvious condition is (m.size() + size) >= threshold, but this
537 * condition could result in a map with twice the appropriate capacity,
557 /**
558 * Removes the mapping for the specified key from this map if present.
559 *
560 * @param key key whose mapping is to be removed from the map
561 * @return the previous value associated with <tt>key</tt>, or
562 * <tt>null</tt> if there was no mapping for <tt>key</tt>.
563 * (A <tt>null</tt> return can also indicate that the map
564 * previously associated <tt>null</tt> with <tt>key</tt>.)
565 */
566 public V remove(Object key) {
567 Entry<K,V> e = removeEntryForKey(key);
568 return (e == null ? null : e.value);
569 }
570
571 /**
572 * Removes and returns the entry associated with the specified key
573 * in the HashMap. Returns null if the HashMap contains no mapping
574 * for this key.
575 */
576 final Entry<K,V> removeEntryForKey(Object key) {
577 int hash = (key == null) ? 0 : hash(key);
578 int i = indexFor(hash, table.length);
579 @SuppressWarnings("unchecked")
580 Entry<K,V> prev = (Entry<K,V>)table[i];
581 Entry<K,V> e = prev;
582
583 while (e != null) {
584 Entry<K,V> next = e.next;
585 Object k;
586 if (e.hash == hash &&
587 ((k = e.key) == key || (key != null && key.equals(k)))) {
588 modCount++;
589 size--;
590 if (prev == e)
591 table[i] = next;
592 else
593 prev.next = next;
594 e.recordRemoval(this);
595 return e;
596 }
597 prev = e;
598 e = next;
599 }
600
601 return e;
602 }
603
604 /**
605 * Special version of remove for EntrySet using {@code Map.Entry.equals()}
606 * for matching.
607 */
608 final Entry<K,V> removeMapping(Object o) {
609 if (!(o instanceof Map.Entry))
610 return null;
611
612 Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
613 Object key = entry.getKey();
614 int hash = (key == null) ? 0 : hash(key.hashCode());
615 int i = indexFor(hash, table.length);
616 @SuppressWarnings("unchecked")
617 Entry<K,V> prev = (Entry<K,V>)table[i];
618 Entry<K,V> e = prev;
619
620 while (e != null) {
621 Entry<K,V> next = e.next;
622 if (e.hash == hash && e.equals(entry)) {
623 modCount++;
624 size--;
625 if (prev == e)
626 table[i] = next;
765 */
766 void recordAccess(HashMap<K,V> m) {
767 }
768
769 /**
770 * This method is invoked whenever the entry is
771 * removed from the table.
772 */
773 void recordRemoval(HashMap<K,V> m) {
774 }
775 }
776
777 /**
778 * Adds a new entry with the specified key, value and hash code to
779 * the specified bucket. It is the responsibility of this
780 * method to resize the table if appropriate.
781 *
782 * Subclass overrides this to alter the behavior of put method.
783 */
784 void addEntry(int hash, K key, V value, int bucketIndex) {
785 if ((size >= threshold) && (null != table[bucketIndex])) {
786 resize(2 * table.length);
787 hash = hash(key);
788 bucketIndex = indexFor(hash, table.length);
789 }
790
791 createEntry(hash, key, value, bucketIndex);
792 }
793
794 /**
795 * Like addEntry except that this version is used when creating entries
796 * as part of Map construction or "pseudo-construction" (cloning,
797 * deserialization). This version needn't worry about resizing the table.
798 *
799 * Subclass overrides this to alter the behavior of HashMap(Map),
800 * clone, and readObject.
801 */
802 void createEntry(int hash, K key, V value, int bucketIndex) {
803 @SuppressWarnings("unchecked")
804 Entry<K,V> e = (Entry<K,V>)table[bucketIndex];
805 table[bucketIndex] = new Entry<>(hash, key, value, e);
806 size++;
807 }
808
809 private abstract class HashIterator<E> implements Iterator<E> {
810 Entry<?,?> next; // next entry to return
811 int expectedModCount; // For fast-fail
835
836 if ((next = e.next) == null) {
837 Entry<?,?>[] t = table;
838 while (index < t.length && (next = t[index++]) == null)
839 ;
840 }
841 current = e;
842 return (Entry<K,V>)e;
843 }
844
845 public void remove() {
846 if (current == null)
847 throw new IllegalStateException();
848 if (modCount != expectedModCount)
849 throw new ConcurrentModificationException();
850 Object k = current.key;
851 current = null;
852 HashMap.this.removeEntryForKey(k);
853 expectedModCount = modCount;
854 }
855 }
856
857 private final class ValueIterator extends HashIterator<V> {
858 public V next() {
859 return nextEntry().value;
860 }
861 }
862
863 private final class KeyIterator extends HashIterator<K> {
864 public K next() {
865 return nextEntry().getKey();
866 }
867 }
868
869 private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
870 public Map.Entry<K,V> next() {
871 return nextEntry();
872 }
873 }
874
1014 * mappings), followed by the key (Object) and value (Object)
1015 * for each key-value mapping. The key-value mappings are
1016 * emitted in no particular order.
1017 */
1018 private void writeObject(java.io.ObjectOutputStream s)
1019 throws IOException
1020 {
1021 Iterator<Map.Entry<K,V>> i =
1022 (size > 0) ? entrySet0().iterator() : null;
1023
1024 // Write out the threshold, loadfactor, and any hidden stuff
1025 s.defaultWriteObject();
1026
1027 // Write out number of buckets
1028 s.writeInt(table.length);
1029
1030 // Write out size (number of Mappings)
1031 s.writeInt(size);
1032
1033 // Write out keys and values (alternating)
1034 if (size > 0) {
1035 for(Map.Entry<K,V> e : entrySet0()) {
1036 s.writeObject(e.getKey());
1037 s.writeObject(e.getValue());
1038 }
1039 }
1040 }
1041
1042 private static final long serialVersionUID = 362498820763181265L;
1043
1044 /**
1045 * Reconstitute the {@code HashMap} instance from a stream (i.e.,
1046 * deserialize it).
1047 */
1048 private void readObject(java.io.ObjectInputStream s)
1049 throws IOException, ClassNotFoundException
1050 {
1051 // Read in the threshold (ignored), loadfactor, and any hidden stuff
1052 s.defaultReadObject();
1053 if (loadFactor <= 0 || Float.isNaN(loadFactor))
1054 throw new InvalidObjectException("Illegal load factor: " +
1055 loadFactor);
1056
1057 // set hashMask
1058 Holder.UNSAFE.putIntVolatile(this, Holder.HASHSEED_OFFSET,
1059 sun.misc.Hashing.randomHashSeed(this));
1060
1061 // Read in number of buckets and allocate the bucket array;
1062 s.readInt(); // ignored
1063
1064 // Read number of mappings
1065 int mappings = s.readInt();
1066 if (mappings < 0)
1067 throw new InvalidObjectException("Illegal mappings count: " +
1068 mappings);
1069
1070 int initialCapacity = (int) Math.min(
1071 // capacity chosen by number of mappings
1072 // and desired load (if >= 0.25)
1073 mappings * Math.min(1 / loadFactor, 4.0f),
1074 // we have limits...
1075 HashMap.MAXIMUM_CAPACITY);
1076 int capacity = 1;
1077 // find smallest power of two which holds all mappings
1078 while (capacity < initialCapacity) {
1079 capacity <<= 1;
1080 }
1081
1082 table = new Entry[capacity];
1083 threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
1084 init(); // Give subclass a chance to do its thing.
1085
1086
1087 // Read the keys and values, and put the mappings in the HashMap
1088 for (int i=0; i<mappings; i++) {
1089 @SuppressWarnings("unchecked")
1090 K key = (K) s.readObject();
1091 @SuppressWarnings("unchecked")
1092 V value = (V) s.readObject();
1093 putForCreate(key, value);
1094 }
1095 }
1096
1097 // These methods are used when serializing HashSets
1098 int capacity() { return table.length; }
1099 float loadFactor() { return loadFactor; }
1100 }
|