< prev index next >

src/java.base/share/classes/java/util/Hashtable.java

Print this page




 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 {


< prev index next >