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() {
285 return size;
286 }
287
288 /**
289 * Returns <tt>true</tt> if this map contains no key-value mappings.
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 private static final sun.misc.Unsafe UNSAFE;
183
184 /**
185 * Offset of "final" hashmask field we must set in
186 * readObject() method.
187 */
188 private static final long HASHMASK_OFFSET;
189
190 static {
191 try {
192 UNSAFE = sun.misc.Unsafe.getUnsafe();
193 HASHMASK_OFFSET = UNSAFE.objectFieldOffset(
194 HashMap.class.getDeclaredField("hashMask"));
195 } catch (NoSuchFieldException | SecurityException e) {
196 throw new InternalError("Failed to record hashMask offset", e);
197 }
198 }
199 }
200
201 /**
202 * A random mask value that is used for hashcode values associated with this
203 * instance to make hash collisions harder to find.
204 */
205 transient final int hashMask = sun.misc.Hashing.makeHashMask(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 = hashMask;
292 if ((0 != h) && (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 h ^= (h >>> 7) ^ (h >>> 4);
303
304 return h;
305 }
306
307 /**
308 * Returns index for hash code h.
309 */
310 static int indexFor(int h, int length) {
311 return h & (length-1);
312 }
313
314 /**
315 * Returns the number of key-value mappings in this map.
316 *
317 * @return the number of key-value mappings in this map
318 */
319 public int size() {
320 return size;
321 }
322
323 /**
324 * Returns <tt>true</tt> if this map contains no key-value mappings.
331
332 /**
333 * Returns the value to which the specified key is mapped,
334 * or {@code null} if this map contains no mapping for the key.
335 *
336 * <p>More formally, if this map contains a mapping from a key
337 * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
338 * key.equals(k))}, then this method returns {@code v}; otherwise
339 * it returns {@code null}. (There can be at most one such mapping.)
340 *
341 * <p>A return value of {@code null} does not <i>necessarily</i>
342 * indicate that the map contains no mapping for the key; it's also
343 * possible that the map explicitly maps the key to {@code null}.
344 * The {@link #containsKey containsKey} operation may be used to
345 * distinguish these two cases.
346 *
347 * @see #put(Object, Object)
348 */
349 @SuppressWarnings("unchecked")
350 public V get(Object key) {
351 Entry<K,V> entry = getEntry(key);
352
353 return null == entry ? null : entry.getValue();
354 }
355
356 /**
357 * Offloaded version of get() to look up null keys. Null keys map
358 * to index 0. This null case is split out into separate methods
359 * for the sake of performance in the two most commonly used
360 * operations (get and put), but incorporated with conditionals in
361 * others.
362 */
363 private Object getForNullKey() {
364 for (Entry<?,?> e = table[0]; e != null; e = e.next) {
365 if (e.key == null)
366 return e.value;
367 }
368 return null;
369 }
370
371 /**
372 * Returns <tt>true</tt> if this map contains a mapping for the
373 * specified key.
374 *
375 * @param key The key whose presence in this map is to be tested
376 * @return <tt>true</tt> if this map contains a mapping for the specified
377 * key.
378 */
379 public boolean containsKey(Object key) {
380 return getEntry(key) != null;
381 }
382
383 /**
384 * Returns the entry associated with the specified key in the
385 * HashMap. Returns null if the HashMap contains no mapping
386 * for the key.
387 */
388 @SuppressWarnings("unchecked")
389 final Entry<K,V> getEntry(Object key) {
390 int hash = (key == null) ? 0 : hash(key);
391 for (Entry<?,?> e = table[indexFor(hash, table.length)];
392 e != null;
393 e = e.next) {
394 Object k;
395 if (e.hash == hash &&
396 ((k = e.key) == key || (key != null && key.equals(k))))
397 return (Entry<K,V>)e;
398 }
399 return null;
400 }
401
402
403 /**
404 * Associates the specified value with the specified key in this map.
405 * If the map previously contained a mapping for the key, the old
406 * value is replaced.
407 *
408 * @param key key with which the specified value is to be associated
409 * @param value value to be associated with the specified key
410 * @return the previous value associated with <tt>key</tt>, or
411 * <tt>null</tt> if there was no mapping for <tt>key</tt>.
412 * (A <tt>null</tt> return can also indicate that the map
413 * previously associated <tt>null</tt> with <tt>key</tt>.)
414 */
415 public V put(K key, V value) {
416 if (key == null)
417 return putForNullKey(value);
418 int hash = hash(key);
419 int i = indexFor(hash, table.length);
420 @SuppressWarnings("unchecked")
421 Entry<K,V> e = (Entry<K,V>)table[i];
422 for(; e != null; e = e.next) {
423 Object k;
424 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
425 V oldValue = e.value;
426 e.value = value;
427 e.recordAccess(this);
428 return oldValue;
429 }
430 }
431
432 modCount++;
433 addEntry(hash, key, value, i);
434 return null;
435 }
436
437 /**
438 * Offloaded version of put for null keys
443 for(; e != null; e = e.next) {
444 if (e.key == null) {
445 V oldValue = e.value;
446 e.value = value;
447 e.recordAccess(this);
448 return oldValue;
449 }
450 }
451 modCount++;
452 addEntry(0, null, value, 0);
453 return null;
454 }
455
456 /**
457 * This method is used instead of put by constructors and
458 * pseudoconstructors (clone, readObject). It does not resize the table,
459 * check for comodification, etc. It calls createEntry rather than
460 * addEntry.
461 */
462 private void putForCreate(K key, V value) {
463 int hash = null == key ? 0 : hash(key);
464 int i = indexFor(hash, table.length);
465
466 /**
467 * Look for preexisting entry for key. This will never happen for
468 * clone or deserialize. It will only happen for construction if the
469 * input Map is a sorted map whose ordering is inconsistent w/ equals.
470 */
471 for (@SuppressWarnings("unchecked")
472 Entry<?,V> e = (Entry<?,V>)table[i]; e != null; e = e.next) {
473 Object k;
474 if (e.hash == hash &&
475 ((k = e.key) == key || (key != null && key.equals(k)))) {
476 e.value = value;
477 return;
478 }
479 }
480
481 createEntry(hash, key, value, i);
482 }
483
494 * If current capacity is MAXIMUM_CAPACITY, this method does not
495 * resize the map, but sets threshold to Integer.MAX_VALUE.
496 * This has the effect of preventing future calls.
497 *
498 * @param newCapacity the new capacity, MUST be a power of two;
499 * must be greater than current capacity unless current
500 * capacity is MAXIMUM_CAPACITY (in which case value
501 * is irrelevant).
502 */
503 void resize(int newCapacity) {
504 Entry<?,?>[] oldTable = table;
505 int oldCapacity = oldTable.length;
506 if (oldCapacity == MAXIMUM_CAPACITY) {
507 threshold = Integer.MAX_VALUE;
508 return;
509 }
510
511 Entry<?,?>[] newTable = new Entry<?,?>[newCapacity];
512 transfer(newTable);
513 table = newTable;
514 threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
515 }
516
517 /**
518 * Transfers all entries from current table to newTable.
519 */
520 @SuppressWarnings("unchecked")
521 void transfer(Entry<?,?>[] newTable) {
522 Entry<?,?>[] src = table;
523 int newCapacity = newTable.length;
524 for (int j = 0; j < src.length; j++ ) {
525 Entry<K,V> e = (Entry<K,V>) src[j];
526 while(null != e) {
527 Entry<K,V> next = e.next;
528 int i = indexFor(e.hash, newCapacity);
529 e.next = (Entry<K,V>) newTable[i];
530 newTable[i] = e;
531 e = next;
532 }
533 }
534 Arrays.fill(table, null);
535 }
536
537 /**
538 * Copies all of the mappings from the specified map to this map.
539 * These mappings will replace any mappings that this map had for
540 * any of the keys currently in the specified map.
541 *
542 * @param m mappings to be stored in this map
543 * @throws NullPointerException if the specified map is null
544 */
545 public void putAll(Map<? extends K, ? extends V> m) {
546 int numKeysToBeAdded = m.size();
547 if (numKeysToBeAdded == 0)
548 return;
549
550 /*
551 * Expand the map if the map if the number of mappings to be added
552 * is greater than or equal to threshold. This is conservative; the
553 * obvious condition is (m.size() + size) >= threshold, but this
554 * condition could result in a map with twice the appropriate capacity,
574 /**
575 * Removes the mapping for the specified key from this map if present.
576 *
577 * @param key key whose mapping is to be removed from the map
578 * @return the previous value associated with <tt>key</tt>, or
579 * <tt>null</tt> if there was no mapping for <tt>key</tt>.
580 * (A <tt>null</tt> return can also indicate that the map
581 * previously associated <tt>null</tt> with <tt>key</tt>.)
582 */
583 public V remove(Object key) {
584 Entry<K,V> e = removeEntryForKey(key);
585 return (e == null ? null : e.value);
586 }
587
588 /**
589 * Removes and returns the entry associated with the specified key
590 * in the HashMap. Returns null if the HashMap contains no mapping
591 * for this key.
592 */
593 final Entry<K,V> removeEntryForKey(Object key) {
594 int hash = (key == null) ? 0 : hash(key);
595 int i = indexFor(hash, table.length);
596 @SuppressWarnings("unchecked")
597 Entry<K,V> prev = (Entry<K,V>)table[i];
598 Entry<K,V> e = prev;
599
600 while (e != null) {
601 Entry<K,V> next = e.next;
602 Object k;
603 if (e.hash == hash &&
604 ((k = e.key) == key || (key != null && key.equals(k)))) {
605 modCount++;
606 size--;
607 if (prev == e)
608 table[i] = next;
609 else
610 prev.next = next;
611 e.recordRemoval(this);
612 return e;
613 }
614 prev = e;
615 e = next;
616 }
617
618 return e;
619 }
620
621 /**
622 * Special version of remove for EntrySet using {@code Map.Entry.equals()}
623 * for matching.
624 */
625 final Entry<K,V> removeMapping(Object o) {
626 if (!(o instanceof Map.Entry))
627 return null;
628
629 Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
630 Object key = entry.getKey();
631 int hash = (key == null) ? 0 : hash(key.hashCode());
632 int i = indexFor(hash, table.length);
633 @SuppressWarnings("unchecked")
634 Entry<K,V> prev = (Entry<K,V>)table[i];
635 Entry<K,V> e = prev;
636
637 while (e != null) {
638 Entry<K,V> next = e.next;
639 if (e.hash == hash && e.equals(entry)) {
640 modCount++;
641 size--;
642 if (prev == e)
643 table[i] = next;
782 */
783 void recordAccess(HashMap<K,V> m) {
784 }
785
786 /**
787 * This method is invoked whenever the entry is
788 * removed from the table.
789 */
790 void recordRemoval(HashMap<K,V> m) {
791 }
792 }
793
794 /**
795 * Adds a new entry with the specified key, value and hash code to
796 * the specified bucket. It is the responsibility of this
797 * method to resize the table if appropriate.
798 *
799 * Subclass overrides this to alter the behavior of put method.
800 */
801 void addEntry(int hash, K key, V value, int bucketIndex) {
802 if ((size >= threshold) && (null != table[bucketIndex])) {
803 resize(2 * table.length);
804 hash = hash(key);
805 bucketIndex = indexFor(hash, table.length);
806 }
807
808 createEntry(hash, key, value, bucketIndex);
809 }
810
811 /**
812 * Like addEntry except that this version is used when creating entries
813 * as part of Map construction or "pseudo-construction" (cloning,
814 * deserialization). This version needn't worry about resizing the table.
815 *
816 * Subclass overrides this to alter the behavior of HashMap(Map),
817 * clone, and readObject.
818 */
819 void createEntry(int hash, K key, V value, int bucketIndex) {
820 @SuppressWarnings("unchecked")
821 Entry<K,V> e = (Entry<K,V>)table[bucketIndex];
822 table[bucketIndex] = new Entry<>(hash, key, value, e);
823 size++;
824 }
825
826 private abstract class HashIterator<E> implements Iterator<E> {
827 Entry<?,?> next; // next entry to return
828 int expectedModCount; // For fast-fail
852
853 if ((next = e.next) == null) {
854 Entry<?,?>[] t = table;
855 while (index < t.length && (next = t[index++]) == null)
856 ;
857 }
858 current = e;
859 return (Entry<K,V>)e;
860 }
861
862 public void remove() {
863 if (current == null)
864 throw new IllegalStateException();
865 if (modCount != expectedModCount)
866 throw new ConcurrentModificationException();
867 Object k = current.key;
868 current = null;
869 HashMap.this.removeEntryForKey(k);
870 expectedModCount = modCount;
871 }
872 }
873
874 private final class ValueIterator extends HashIterator<V> {
875 public V next() {
876 return nextEntry().value;
877 }
878 }
879
880 private final class KeyIterator extends HashIterator<K> {
881 public K next() {
882 return nextEntry().getKey();
883 }
884 }
885
886 private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
887 public Map.Entry<K,V> next() {
888 return nextEntry();
889 }
890 }
891
1031 * mappings), followed by the key (Object) and value (Object)
1032 * for each key-value mapping. The key-value mappings are
1033 * emitted in no particular order.
1034 */
1035 private void writeObject(java.io.ObjectOutputStream s)
1036 throws IOException
1037 {
1038 Iterator<Map.Entry<K,V>> i =
1039 (size > 0) ? entrySet0().iterator() : null;
1040
1041 // Write out the threshold, loadfactor, and any hidden stuff
1042 s.defaultWriteObject();
1043
1044 // Write out number of buckets
1045 s.writeInt(table.length);
1046
1047 // Write out size (number of Mappings)
1048 s.writeInt(size);
1049
1050 // Write out keys and values (alternating)
1051 if (size > 0) {
1052 for(Map.Entry<K,V> e : entrySet0()) {
1053 s.writeObject(e.getKey());
1054 s.writeObject(e.getValue());
1055 }
1056 }
1057 }
1058
1059 private static final long serialVersionUID = 362498820763181265L;
1060
1061 /**
1062 * Reconstitute the {@code HashMap} instance from a stream (i.e.,
1063 * deserialize it).
1064 */
1065 private void readObject(java.io.ObjectInputStream s)
1066 throws IOException, ClassNotFoundException
1067 {
1068 // Read in the threshold (ignored), loadfactor, and any hidden stuff
1069 s.defaultReadObject();
1070 if (loadFactor <= 0 || Float.isNaN(loadFactor))
1071 throw new InvalidObjectException("Illegal load factor: " +
1072 loadFactor);
1073
1074 // set hashMask
1075 Holder.UNSAFE.putIntVolatile(this, Holder.HASHMASK_OFFSET,
1076 sun.misc.Hashing.makeHashMask(this));
1077
1078 // Read in number of buckets and allocate the bucket array;
1079 s.readInt(); // ignored
1080
1081 // Read number of mappings
1082 int mappings = s.readInt();
1083 if (mappings < 0)
1084 throw new InvalidObjectException("Illegal mappings count: " +
1085 mappings);
1086
1087 int initialCapacity = (int) Math.min(
1088 // capacity chosen by number of mappings
1089 // and desired load (if >= 0.25)
1090 mappings * Math.min(1 / loadFactor, 4.0f),
1091 // we have limits...
1092 HashMap.MAXIMUM_CAPACITY);
1093 int capacity = 1;
1094 // find smallest power of two which holds all mappings
1095 while (capacity < initialCapacity) {
1096 capacity <<= 1;
1097 }
1098
1099 table = new Entry[capacity];
1100 threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
1101 init(); // Give subclass a chance to do its thing.
1102
1103
1104 // Read the keys and values, and put the mappings in the HashMap
1105 for (int i=0; i<mappings; i++) {
1106 @SuppressWarnings("unchecked")
1107 K key = (K) s.readObject();
1108 @SuppressWarnings("unchecked")
1109 V value = (V) s.readObject();
1110 putForCreate(key, value);
1111 }
1112 }
1113
1114 // These methods are used when serializing HashSets
1115 int capacity() { return table.length; }
1116 float loadFactor() { return loadFactor; }
1117 }
|