293 * Tests if some key maps into the specified value in this hashtable.
294 * This operation is more expensive than the {@link #containsKey
295 * containsKey} method.
296 *
297 * <p>Note that this method is identical in functionality to
298 * {@link #containsValue containsValue}, (which is part of the
299 * {@link Map} interface in the collections framework).
300 *
301 * @param value a value to search for
302 * @return {@code true} if and only if some key maps to the
303 * {@code value} argument in this hashtable as
304 * determined by the {@code equals} method;
305 * {@code false} otherwise.
306 * @exception NullPointerException if the value is {@code null}
307 */
308 public synchronized boolean contains(Object value) {
309 if (value == null) {
310 throw new NullPointerException();
311 }
312
313 Entry<?,?> tab[] = table;
314 for (int i = tab.length ; i-- > 0 ;) {
315 for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
316 if (e.value.equals(value)) {
317 return true;
318 }
319 }
320 }
321 return false;
322 }
323
324 /**
325 * Returns true if this hashtable maps one or more keys to this value.
326 *
327 * <p>Note that this method is identical in functionality to {@link
328 * #contains contains} (which predates the {@link Map} interface).
329 *
330 * @param value value whose presence in this hashtable is to be tested
331 * @return {@code true} if this map maps one or more keys to the
332 * specified value
333 * @throws NullPointerException if the value is {@code null}
334 * @since 1.2
335 */
336 public boolean containsValue(Object value) {
337 return contains(value);
338 }
339
340 /**
341 * Tests if the specified object is a key in this hashtable.
342 *
343 * @param key possible key
344 * @return {@code true} if and only if the specified object
345 * is a key in this hashtable, as determined by the
346 * {@code equals} method; {@code false} otherwise.
347 * @throws NullPointerException if the key is {@code null}
348 * @see #contains(Object)
349 */
350 public synchronized boolean containsKey(Object key) {
351 Entry<?,?> tab[] = table;
352 int hash = key.hashCode();
353 int index = (hash & 0x7FFFFFFF) % tab.length;
354 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
355 if ((e.hash == hash) && e.key.equals(key)) {
356 return true;
357 }
358 }
359 return false;
360 }
361
362 /**
363 * Returns the value to which the specified key is mapped,
364 * or {@code null} if this map contains no mapping for the key.
365 *
366 * <p>More formally, if this map contains a mapping from a key
367 * {@code k} to a value {@code v} such that {@code (key.equals(k))},
368 * then this method returns {@code v}; otherwise it returns
369 * {@code null}. (There can be at most one such mapping.)
370 *
371 * @param key the key whose associated value is to be returned
372 * @return the value to which the specified key is mapped, or
373 * {@code null} if this map contains no mapping for the key
374 * @throws NullPointerException if the specified key is null
375 * @see #put(Object, Object)
376 */
377 @SuppressWarnings("unchecked")
378 public synchronized V get(Object key) {
379 Entry<?,?> tab[] = table;
380 int hash = key.hashCode();
381 int index = (hash & 0x7FFFFFFF) % tab.length;
382 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
383 if ((e.hash == hash) && e.key.equals(key)) {
384 return (V)e.value;
385 }
386 }
387 return null;
388 }
389
390 /**
391 * The maximum size of array to allocate.
392 * Some VMs reserve some header words in an array.
393 * Attempts to allocate larger arrays may result in
394 * OutOfMemoryError: Requested array size exceeds VM limit
395 */
396 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
397
398 /**
399 * Increases the capacity of and internally reorganizes this
417 }
418 Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
419
420 modCount++;
421 threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
422 table = newMap;
423
424 for (int i = oldCapacity ; i-- > 0 ;) {
425 for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
426 Entry<K,V> e = old;
427 old = old.next;
428
429 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
430 e.next = (Entry<K,V>)newMap[index];
431 newMap[index] = e;
432 }
433 }
434 }
435
436 private void addEntry(int hash, K key, V value, int index) {
437 Entry<?,?> tab[] = table;
438 if (count >= threshold) {
439 // Rehash the table if the threshold is exceeded
440 rehash();
441
442 tab = table;
443 hash = key.hashCode();
444 index = (hash & 0x7FFFFFFF) % tab.length;
445 }
446
447 // Creates the new entry.
448 @SuppressWarnings("unchecked")
449 Entry<K,V> e = (Entry<K,V>) tab[index];
450 tab[index] = new Entry<>(hash, key, value, e);
451 count++;
452 modCount++;
453 }
454
455 /**
456 * Maps the specified {@code key} to the specified
457 * {@code value} in this hashtable. Neither the key nor the
459 *
460 * The value can be retrieved by calling the {@code get} method
461 * with a key that is equal to the original key.
462 *
463 * @param key the hashtable key
464 * @param value the value
465 * @return the previous value of the specified key in this hashtable,
466 * or {@code null} if it did not have one
467 * @exception NullPointerException if the key or value is
468 * {@code null}
469 * @see Object#equals(Object)
470 * @see #get(Object)
471 */
472 public synchronized V put(K key, V value) {
473 // Make sure the value is not null
474 if (value == null) {
475 throw new NullPointerException();
476 }
477
478 // Makes sure the key is not already in the hashtable.
479 Entry<?,?> tab[] = table;
480 int hash = key.hashCode();
481 int index = (hash & 0x7FFFFFFF) % tab.length;
482 @SuppressWarnings("unchecked")
483 Entry<K,V> entry = (Entry<K,V>)tab[index];
484 for(; entry != null ; entry = entry.next) {
485 if ((entry.hash == hash) && entry.key.equals(key)) {
486 V old = entry.value;
487 entry.value = value;
488 return old;
489 }
490 }
491
492 addEntry(hash, key, value, index);
493 return null;
494 }
495
496 /**
497 * Removes the key (and its corresponding value) from this
498 * hashtable. This method does nothing if the key is not in the hashtable.
499 *
500 * @param key the key that needs to be removed
501 * @return the value to which the key had been mapped in this hashtable,
502 * or {@code null} if the key did not have a mapping
503 * @throws NullPointerException if the key is {@code null}
504 */
505 public synchronized V remove(Object key) {
506 Entry<?,?> tab[] = table;
507 int hash = key.hashCode();
508 int index = (hash & 0x7FFFFFFF) % tab.length;
509 @SuppressWarnings("unchecked")
510 Entry<K,V> e = (Entry<K,V>)tab[index];
511 for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
512 if ((e.hash == hash) && e.key.equals(key)) {
513 if (prev != null) {
514 prev.next = e.next;
515 } else {
516 tab[index] = e.next;
517 }
518 modCount++;
519 count--;
520 V oldValue = e.value;
521 e.value = null;
522 return oldValue;
523 }
524 }
525 return null;
526 }
527
528 /**
529 * Copies all of the mappings from the specified map to this hashtable.
530 * These mappings will replace any mappings that this hashtable had for any
531 * of the keys currently in the specified map.
532 *
533 * @param t mappings to be stored in this map
534 * @throws NullPointerException if the specified map is null
535 * @since 1.2
536 */
537 public synchronized void putAll(Map<? extends K, ? extends V> t) {
538 for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
539 put(e.getKey(), e.getValue());
540 }
541
542 /**
543 * Clears this hashtable so that it contains no keys.
544 */
545 public synchronized void clear() {
546 Entry<?,?> tab[] = table;
547 for (int index = tab.length; --index >= 0; )
548 tab[index] = null;
549 modCount++;
550 count = 0;
551 }
552
553 /**
554 * Creates a shallow copy of this hashtable. All the structure of the
555 * hashtable itself is copied, but the keys and values are not cloned.
556 * This is a relatively expensive operation.
557 *
558 * @return a clone of the hashtable
559 */
560 public synchronized Object clone() {
561 Hashtable<?,?> t = cloneHashtable();
562 t.table = new Entry<?,?>[table.length];
563 for (int i = table.length ; i-- > 0 ; ) {
564 t.table[i] = (table[i] != null)
565 ? (Entry<?,?>) table[i].clone() : null;
566 }
913
914 Entry<K, V>[] tab = (Entry<K, V>[])table;
915 for (Entry<K, V> entry : tab) {
916 while (entry != null) {
917 entry.value = Objects.requireNonNull(
918 function.apply(entry.key, entry.value));
919 entry = entry.next;
920
921 if (expectedModCount != modCount) {
922 throw new ConcurrentModificationException();
923 }
924 }
925 }
926 }
927
928 @Override
929 public synchronized V putIfAbsent(K key, V value) {
930 Objects.requireNonNull(value);
931
932 // Makes sure the key is not already in the hashtable.
933 Entry<?,?> tab[] = table;
934 int hash = key.hashCode();
935 int index = (hash & 0x7FFFFFFF) % tab.length;
936 @SuppressWarnings("unchecked")
937 Entry<K,V> entry = (Entry<K,V>)tab[index];
938 for (; entry != null; entry = entry.next) {
939 if ((entry.hash == hash) && entry.key.equals(key)) {
940 V old = entry.value;
941 if (old == null) {
942 entry.value = value;
943 }
944 return old;
945 }
946 }
947
948 addEntry(hash, key, value, index);
949 return null;
950 }
951
952 @Override
953 public synchronized boolean remove(Object key, Object value) {
954 Objects.requireNonNull(value);
955
956 Entry<?,?> tab[] = table;
957 int hash = key.hashCode();
958 int index = (hash & 0x7FFFFFFF) % tab.length;
959 @SuppressWarnings("unchecked")
960 Entry<K,V> e = (Entry<K,V>)tab[index];
961 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
962 if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) {
963 if (prev != null) {
964 prev.next = e.next;
965 } else {
966 tab[index] = e.next;
967 }
968 e.value = null; // clear for gc
969 modCount++;
970 count--;
971 return true;
972 }
973 }
974 return false;
975 }
976
977 @Override
978 public synchronized boolean replace(K key, V oldValue, V newValue) {
979 Objects.requireNonNull(oldValue);
980 Objects.requireNonNull(newValue);
981 Entry<?,?> tab[] = table;
982 int hash = key.hashCode();
983 int index = (hash & 0x7FFFFFFF) % tab.length;
984 @SuppressWarnings("unchecked")
985 Entry<K,V> e = (Entry<K,V>)tab[index];
986 for (; e != null; e = e.next) {
987 if ((e.hash == hash) && e.key.equals(key)) {
988 if (e.value.equals(oldValue)) {
989 e.value = newValue;
990 return true;
991 } else {
992 return false;
993 }
994 }
995 }
996 return false;
997 }
998
999 @Override
1000 public synchronized V replace(K key, V value) {
1001 Objects.requireNonNull(value);
1002 Entry<?,?> tab[] = table;
1003 int hash = key.hashCode();
1004 int index = (hash & 0x7FFFFFFF) % tab.length;
1005 @SuppressWarnings("unchecked")
1006 Entry<K,V> e = (Entry<K,V>)tab[index];
1007 for (; e != null; e = e.next) {
1008 if ((e.hash == hash) && e.key.equals(key)) {
1009 V oldValue = e.value;
1010 e.value = value;
1011 return oldValue;
1012 }
1013 }
1014 return null;
1015 }
1016
1017 /**
1018 * {@inheritDoc}
1019 *
1020 * <p>This method will, on a best-effort basis, throw a
1021 * {@link java.util.ConcurrentModificationException} if the mapping
1022 * function modified this map during computation.
1023 *
1024 * @throws ConcurrentModificationException if it is detected that the
1025 * mapping function modified this map
1026 */
1027 @Override
1028 public synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
1029 Objects.requireNonNull(mappingFunction);
1030
1031 Entry<?,?> tab[] = table;
1032 int hash = key.hashCode();
1033 int index = (hash & 0x7FFFFFFF) % tab.length;
1034 @SuppressWarnings("unchecked")
1035 Entry<K,V> e = (Entry<K,V>)tab[index];
1036 for (; e != null; e = e.next) {
1037 if (e.hash == hash && e.key.equals(key)) {
1038 // Hashtable not accept null value
1039 return e.value;
1040 }
1041 }
1042
1043 int mc = modCount;
1044 V newValue = mappingFunction.apply(key);
1045 if (mc != modCount) { throw new ConcurrentModificationException(); }
1046 if (newValue != null) {
1047 addEntry(hash, key, newValue, index);
1048 }
1049
1050 return newValue;
1051 }
1052
1053 /**
1054 * {@inheritDoc}
1055 *
1056 * <p>This method will, on a best-effort basis, throw a
1057 * {@link java.util.ConcurrentModificationException} if the remapping
1058 * function modified this map during computation.
1059 *
1060 * @throws ConcurrentModificationException if it is detected that the
1061 * remapping function modified this map
1062 */
1063 @Override
1064 public synchronized V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
1065 Objects.requireNonNull(remappingFunction);
1066
1067 Entry<?,?> tab[] = table;
1068 int hash = key.hashCode();
1069 int index = (hash & 0x7FFFFFFF) % tab.length;
1070 @SuppressWarnings("unchecked")
1071 Entry<K,V> e = (Entry<K,V>)tab[index];
1072 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
1073 if (e.hash == hash && e.key.equals(key)) {
1074 int mc = modCount;
1075 V newValue = remappingFunction.apply(key, e.value);
1076 if (mc != modCount) {
1077 throw new ConcurrentModificationException();
1078 }
1079 if (newValue == null) {
1080 if (prev != null) {
1081 prev.next = e.next;
1082 } else {
1083 tab[index] = e.next;
1084 }
1085 modCount = mc + 1;
1086 count--;
1087 } else {
1089 }
1090 return newValue;
1091 }
1092 }
1093 return null;
1094 }
1095 /**
1096 * {@inheritDoc}
1097 *
1098 * <p>This method will, on a best-effort basis, throw a
1099 * {@link java.util.ConcurrentModificationException} if the remapping
1100 * function modified this map during computation.
1101 *
1102 * @throws ConcurrentModificationException if it is detected that the
1103 * remapping function modified this map
1104 */
1105 @Override
1106 public synchronized V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
1107 Objects.requireNonNull(remappingFunction);
1108
1109 Entry<?,?> tab[] = table;
1110 int hash = key.hashCode();
1111 int index = (hash & 0x7FFFFFFF) % tab.length;
1112 @SuppressWarnings("unchecked")
1113 Entry<K,V> e = (Entry<K,V>)tab[index];
1114 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
1115 if (e.hash == hash && Objects.equals(e.key, key)) {
1116 int mc = modCount;
1117 V newValue = remappingFunction.apply(key, e.value);
1118 if (mc != modCount) {
1119 throw new ConcurrentModificationException();
1120 }
1121 if (newValue == null) {
1122 if (prev != null) {
1123 prev.next = e.next;
1124 } else {
1125 tab[index] = e.next;
1126 }
1127 modCount = mc + 1;
1128 count--;
1129 } else {
1140 addEntry(hash, key, newValue, index);
1141 }
1142
1143 return newValue;
1144 }
1145
1146 /**
1147 * {@inheritDoc}
1148 *
1149 * <p>This method will, on a best-effort basis, throw a
1150 * {@link java.util.ConcurrentModificationException} if the remapping
1151 * function modified this map during computation.
1152 *
1153 * @throws ConcurrentModificationException if it is detected that the
1154 * remapping function modified this map
1155 */
1156 @Override
1157 public synchronized V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
1158 Objects.requireNonNull(remappingFunction);
1159
1160 Entry<?,?> tab[] = table;
1161 int hash = key.hashCode();
1162 int index = (hash & 0x7FFFFFFF) % tab.length;
1163 @SuppressWarnings("unchecked")
1164 Entry<K,V> e = (Entry<K,V>)tab[index];
1165 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
1166 if (e.hash == hash && e.key.equals(key)) {
1167 int mc = modCount;
1168 V newValue = remappingFunction.apply(e.value, value);
1169 if (mc != modCount) {
1170 throw new ConcurrentModificationException();
1171 }
1172 if (newValue == null) {
1173 if (prev != null) {
1174 prev.next = e.next;
1175 } else {
1176 tab[index] = e.next;
1177 }
1178 modCount = mc + 1;
1179 count--;
1180 } else {
|
293 * Tests if some key maps into the specified value in this hashtable.
294 * This operation is more expensive than the {@link #containsKey
295 * containsKey} method.
296 *
297 * <p>Note that this method is identical in functionality to
298 * {@link #containsValue containsValue}, (which is part of the
299 * {@link Map} interface in the collections framework).
300 *
301 * @param value a value to search for
302 * @return {@code true} if and only if some key maps to the
303 * {@code value} argument in this hashtable as
304 * determined by the {@code equals} method;
305 * {@code false} otherwise.
306 * @exception NullPointerException if the value is {@code null}
307 */
308 public synchronized boolean contains(Object value) {
309 if (value == null) {
310 throw new NullPointerException();
311 }
312
313 Entry<?,?>[] tab = table;
314 for (int i = tab.length ; i-- > 0 ;) {
315 for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
316 if (e.value.equals(value)) {
317 return true;
318 }
319 }
320 }
321 return false;
322 }
323
324 /**
325 * Returns true if this hashtable maps one or more keys to this value.
326 *
327 * <p>Note that this method is identical in functionality to {@link
328 * #contains contains} (which predates the {@link Map} interface).
329 *
330 * @param value value whose presence in this hashtable is to be tested
331 * @return {@code true} if this map maps one or more keys to the
332 * specified value
333 * @throws NullPointerException if the value is {@code null}
334 * @since 1.2
335 */
336 public boolean containsValue(Object value) {
337 return contains(value);
338 }
339
340 /**
341 * Tests if the specified object is a key in this hashtable.
342 *
343 * @param key possible key
344 * @return {@code true} if and only if the specified object
345 * is a key in this hashtable, as determined by the
346 * {@code equals} method; {@code false} otherwise.
347 * @throws NullPointerException if the key is {@code null}
348 * @see #contains(Object)
349 */
350 public synchronized boolean containsKey(Object key) {
351 Entry<?,?>[] tab = table;
352 int hash = key.hashCode();
353 int index = (hash & 0x7FFFFFFF) % tab.length;
354 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
355 if ((e.hash == hash) && e.key.equals(key)) {
356 return true;
357 }
358 }
359 return false;
360 }
361
362 /**
363 * Returns the value to which the specified key is mapped,
364 * or {@code null} if this map contains no mapping for the key.
365 *
366 * <p>More formally, if this map contains a mapping from a key
367 * {@code k} to a value {@code v} such that {@code (key.equals(k))},
368 * then this method returns {@code v}; otherwise it returns
369 * {@code null}. (There can be at most one such mapping.)
370 *
371 * @param key the key whose associated value is to be returned
372 * @return the value to which the specified key is mapped, or
373 * {@code null} if this map contains no mapping for the key
374 * @throws NullPointerException if the specified key is null
375 * @see #put(Object, Object)
376 */
377 @SuppressWarnings("unchecked")
378 public synchronized V get(Object key) {
379 Entry<?,?>[] tab = table;
380 int hash = key.hashCode();
381 int index = (hash & 0x7FFFFFFF) % tab.length;
382 for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
383 if ((e.hash == hash) && e.key.equals(key)) {
384 return (V)e.value;
385 }
386 }
387 return null;
388 }
389
390 /**
391 * The maximum size of array to allocate.
392 * Some VMs reserve some header words in an array.
393 * Attempts to allocate larger arrays may result in
394 * OutOfMemoryError: Requested array size exceeds VM limit
395 */
396 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
397
398 /**
399 * Increases the capacity of and internally reorganizes this
417 }
418 Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
419
420 modCount++;
421 threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
422 table = newMap;
423
424 for (int i = oldCapacity ; i-- > 0 ;) {
425 for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
426 Entry<K,V> e = old;
427 old = old.next;
428
429 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
430 e.next = (Entry<K,V>)newMap[index];
431 newMap[index] = e;
432 }
433 }
434 }
435
436 private void addEntry(int hash, K key, V value, int index) {
437 Entry<?,?>[] tab = table;
438 if (count >= threshold) {
439 // Rehash the table if the threshold is exceeded
440 rehash();
441
442 tab = table;
443 hash = key.hashCode();
444 index = (hash & 0x7FFFFFFF) % tab.length;
445 }
446
447 // Creates the new entry.
448 @SuppressWarnings("unchecked")
449 Entry<K,V> e = (Entry<K,V>) tab[index];
450 tab[index] = new Entry<>(hash, key, value, e);
451 count++;
452 modCount++;
453 }
454
455 /**
456 * Maps the specified {@code key} to the specified
457 * {@code value} in this hashtable. Neither the key nor the
459 *
460 * The value can be retrieved by calling the {@code get} method
461 * with a key that is equal to the original key.
462 *
463 * @param key the hashtable key
464 * @param value the value
465 * @return the previous value of the specified key in this hashtable,
466 * or {@code null} if it did not have one
467 * @exception NullPointerException if the key or value is
468 * {@code null}
469 * @see Object#equals(Object)
470 * @see #get(Object)
471 */
472 public synchronized V put(K key, V value) {
473 // Make sure the value is not null
474 if (value == null) {
475 throw new NullPointerException();
476 }
477
478 // Makes sure the key is not already in the hashtable.
479 Entry<?,?>[] tab = table;
480 int hash = key.hashCode();
481 int index = (hash & 0x7FFFFFFF) % tab.length;
482 @SuppressWarnings("unchecked")
483 Entry<K,V> entry = (Entry<K,V>)tab[index];
484 for(; entry != null ; entry = entry.next) {
485 if ((entry.hash == hash) && entry.key.equals(key)) {
486 V old = entry.value;
487 entry.value = value;
488 return old;
489 }
490 }
491
492 addEntry(hash, key, value, index);
493 return null;
494 }
495
496 /**
497 * Removes the key (and its corresponding value) from this
498 * hashtable. This method does nothing if the key is not in the hashtable.
499 *
500 * @param key the key that needs to be removed
501 * @return the value to which the key had been mapped in this hashtable,
502 * or {@code null} if the key did not have a mapping
503 * @throws NullPointerException if the key is {@code null}
504 */
505 public synchronized V remove(Object key) {
506 Entry<?,?>[] tab = table;
507 int hash = key.hashCode();
508 int index = (hash & 0x7FFFFFFF) % tab.length;
509 @SuppressWarnings("unchecked")
510 Entry<K,V> e = (Entry<K,V>)tab[index];
511 for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
512 if ((e.hash == hash) && e.key.equals(key)) {
513 if (prev != null) {
514 prev.next = e.next;
515 } else {
516 tab[index] = e.next;
517 }
518 modCount++;
519 count--;
520 V oldValue = e.value;
521 e.value = null;
522 return oldValue;
523 }
524 }
525 return null;
526 }
527
528 /**
529 * Copies all of the mappings from the specified map to this hashtable.
530 * These mappings will replace any mappings that this hashtable had for any
531 * of the keys currently in the specified map.
532 *
533 * @param t mappings to be stored in this map
534 * @throws NullPointerException if the specified map is null
535 * @since 1.2
536 */
537 public synchronized void putAll(Map<? extends K, ? extends V> t) {
538 for (Map.Entry<? extends K, ? extends V> e : t.entrySet())
539 put(e.getKey(), e.getValue());
540 }
541
542 /**
543 * Clears this hashtable so that it contains no keys.
544 */
545 public synchronized void clear() {
546 Entry<?,?>[] tab = table;
547 for (int index = tab.length; --index >= 0; )
548 tab[index] = null;
549 modCount++;
550 count = 0;
551 }
552
553 /**
554 * Creates a shallow copy of this hashtable. All the structure of the
555 * hashtable itself is copied, but the keys and values are not cloned.
556 * This is a relatively expensive operation.
557 *
558 * @return a clone of the hashtable
559 */
560 public synchronized Object clone() {
561 Hashtable<?,?> t = cloneHashtable();
562 t.table = new Entry<?,?>[table.length];
563 for (int i = table.length ; i-- > 0 ; ) {
564 t.table[i] = (table[i] != null)
565 ? (Entry<?,?>) table[i].clone() : null;
566 }
913
914 Entry<K, V>[] tab = (Entry<K, V>[])table;
915 for (Entry<K, V> entry : tab) {
916 while (entry != null) {
917 entry.value = Objects.requireNonNull(
918 function.apply(entry.key, entry.value));
919 entry = entry.next;
920
921 if (expectedModCount != modCount) {
922 throw new ConcurrentModificationException();
923 }
924 }
925 }
926 }
927
928 @Override
929 public synchronized V putIfAbsent(K key, V value) {
930 Objects.requireNonNull(value);
931
932 // Makes sure the key is not already in the hashtable.
933 Entry<?,?>[] tab = table;
934 int hash = key.hashCode();
935 int index = (hash & 0x7FFFFFFF) % tab.length;
936 @SuppressWarnings("unchecked")
937 Entry<K,V> entry = (Entry<K,V>)tab[index];
938 for (; entry != null; entry = entry.next) {
939 if ((entry.hash == hash) && entry.key.equals(key)) {
940 V old = entry.value;
941 if (old == null) {
942 entry.value = value;
943 }
944 return old;
945 }
946 }
947
948 addEntry(hash, key, value, index);
949 return null;
950 }
951
952 @Override
953 public synchronized boolean remove(Object key, Object value) {
954 Objects.requireNonNull(value);
955
956 Entry<?,?>[] tab = table;
957 int hash = key.hashCode();
958 int index = (hash & 0x7FFFFFFF) % tab.length;
959 @SuppressWarnings("unchecked")
960 Entry<K,V> e = (Entry<K,V>)tab[index];
961 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
962 if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) {
963 if (prev != null) {
964 prev.next = e.next;
965 } else {
966 tab[index] = e.next;
967 }
968 e.value = null; // clear for gc
969 modCount++;
970 count--;
971 return true;
972 }
973 }
974 return false;
975 }
976
977 @Override
978 public synchronized boolean replace(K key, V oldValue, V newValue) {
979 Objects.requireNonNull(oldValue);
980 Objects.requireNonNull(newValue);
981 Entry<?,?>[] tab = table;
982 int hash = key.hashCode();
983 int index = (hash & 0x7FFFFFFF) % tab.length;
984 @SuppressWarnings("unchecked")
985 Entry<K,V> e = (Entry<K,V>)tab[index];
986 for (; e != null; e = e.next) {
987 if ((e.hash == hash) && e.key.equals(key)) {
988 if (e.value.equals(oldValue)) {
989 e.value = newValue;
990 return true;
991 } else {
992 return false;
993 }
994 }
995 }
996 return false;
997 }
998
999 @Override
1000 public synchronized V replace(K key, V value) {
1001 Objects.requireNonNull(value);
1002 Entry<?,?>[] tab = table;
1003 int hash = key.hashCode();
1004 int index = (hash & 0x7FFFFFFF) % tab.length;
1005 @SuppressWarnings("unchecked")
1006 Entry<K,V> e = (Entry<K,V>)tab[index];
1007 for (; e != null; e = e.next) {
1008 if ((e.hash == hash) && e.key.equals(key)) {
1009 V oldValue = e.value;
1010 e.value = value;
1011 return oldValue;
1012 }
1013 }
1014 return null;
1015 }
1016
1017 /**
1018 * {@inheritDoc}
1019 *
1020 * <p>This method will, on a best-effort basis, throw a
1021 * {@link java.util.ConcurrentModificationException} if the mapping
1022 * function modified this map during computation.
1023 *
1024 * @throws ConcurrentModificationException if it is detected that the
1025 * mapping function modified this map
1026 */
1027 @Override
1028 public synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
1029 Objects.requireNonNull(mappingFunction);
1030
1031 Entry<?,?>[] tab = table;
1032 int hash = key.hashCode();
1033 int index = (hash & 0x7FFFFFFF) % tab.length;
1034 @SuppressWarnings("unchecked")
1035 Entry<K,V> e = (Entry<K,V>)tab[index];
1036 for (; e != null; e = e.next) {
1037 if (e.hash == hash && e.key.equals(key)) {
1038 // Hashtable not accept null value
1039 return e.value;
1040 }
1041 }
1042
1043 int mc = modCount;
1044 V newValue = mappingFunction.apply(key);
1045 if (mc != modCount) { throw new ConcurrentModificationException(); }
1046 if (newValue != null) {
1047 addEntry(hash, key, newValue, index);
1048 }
1049
1050 return newValue;
1051 }
1052
1053 /**
1054 * {@inheritDoc}
1055 *
1056 * <p>This method will, on a best-effort basis, throw a
1057 * {@link java.util.ConcurrentModificationException} if the remapping
1058 * function modified this map during computation.
1059 *
1060 * @throws ConcurrentModificationException if it is detected that the
1061 * remapping function modified this map
1062 */
1063 @Override
1064 public synchronized V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
1065 Objects.requireNonNull(remappingFunction);
1066
1067 Entry<?,?>[] tab = table;
1068 int hash = key.hashCode();
1069 int index = (hash & 0x7FFFFFFF) % tab.length;
1070 @SuppressWarnings("unchecked")
1071 Entry<K,V> e = (Entry<K,V>)tab[index];
1072 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
1073 if (e.hash == hash && e.key.equals(key)) {
1074 int mc = modCount;
1075 V newValue = remappingFunction.apply(key, e.value);
1076 if (mc != modCount) {
1077 throw new ConcurrentModificationException();
1078 }
1079 if (newValue == null) {
1080 if (prev != null) {
1081 prev.next = e.next;
1082 } else {
1083 tab[index] = e.next;
1084 }
1085 modCount = mc + 1;
1086 count--;
1087 } else {
1089 }
1090 return newValue;
1091 }
1092 }
1093 return null;
1094 }
1095 /**
1096 * {@inheritDoc}
1097 *
1098 * <p>This method will, on a best-effort basis, throw a
1099 * {@link java.util.ConcurrentModificationException} if the remapping
1100 * function modified this map during computation.
1101 *
1102 * @throws ConcurrentModificationException if it is detected that the
1103 * remapping function modified this map
1104 */
1105 @Override
1106 public synchronized V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
1107 Objects.requireNonNull(remappingFunction);
1108
1109 Entry<?,?>[] tab = table;
1110 int hash = key.hashCode();
1111 int index = (hash & 0x7FFFFFFF) % tab.length;
1112 @SuppressWarnings("unchecked")
1113 Entry<K,V> e = (Entry<K,V>)tab[index];
1114 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
1115 if (e.hash == hash && Objects.equals(e.key, key)) {
1116 int mc = modCount;
1117 V newValue = remappingFunction.apply(key, e.value);
1118 if (mc != modCount) {
1119 throw new ConcurrentModificationException();
1120 }
1121 if (newValue == null) {
1122 if (prev != null) {
1123 prev.next = e.next;
1124 } else {
1125 tab[index] = e.next;
1126 }
1127 modCount = mc + 1;
1128 count--;
1129 } else {
1140 addEntry(hash, key, newValue, index);
1141 }
1142
1143 return newValue;
1144 }
1145
1146 /**
1147 * {@inheritDoc}
1148 *
1149 * <p>This method will, on a best-effort basis, throw a
1150 * {@link java.util.ConcurrentModificationException} if the remapping
1151 * function modified this map during computation.
1152 *
1153 * @throws ConcurrentModificationException if it is detected that the
1154 * remapping function modified this map
1155 */
1156 @Override
1157 public synchronized V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
1158 Objects.requireNonNull(remappingFunction);
1159
1160 Entry<?,?>[] tab = table;
1161 int hash = key.hashCode();
1162 int index = (hash & 0x7FFFFFFF) % tab.length;
1163 @SuppressWarnings("unchecked")
1164 Entry<K,V> e = (Entry<K,V>)tab[index];
1165 for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
1166 if (e.hash == hash && e.key.equals(key)) {
1167 int mc = modCount;
1168 V newValue = remappingFunction.apply(e.value, value);
1169 if (mc != modCount) {
1170 throw new ConcurrentModificationException();
1171 }
1172 if (newValue == null) {
1173 if (prev != null) {
1174 prev.next = e.next;
1175 } else {
1176 tab[index] = e.next;
1177 }
1178 modCount = mc + 1;
1179 count--;
1180 } else {
|