112 *
113 * @author Arthur van Hoff
114 * @author Josh Bloch
115 * @author Neal Gafter
116 * @see Object#equals(java.lang.Object)
117 * @see Object#hashCode()
118 * @see Hashtable#rehash()
119 * @see Collection
120 * @see Map
121 * @see HashMap
122 * @see TreeMap
123 * @since JDK1.0
124 */
125 public class Hashtable<K,V>
126 extends Dictionary<K,V>
127 implements Map<K,V>, Cloneable, java.io.Serializable {
128
129 /**
130 * The hash table data.
131 */
132 private transient Entry[] table;
133
134 /**
135 * The total number of entries in the hash table.
136 */
137 private transient int count;
138
139 /**
140 * The table is rehashed when its size exceeds this threshold. (The
141 * value of this field is (int)(capacity * loadFactor).)
142 *
143 * @serial
144 */
145 private int threshold;
146
147 /**
148 * The load factor for the hashtable.
149 *
150 * @serial
151 */
152 private float loadFactor;
153
154 /**
155 * The number of times this Hashtable has been structurally modified
156 * Structural modifications are those that change the number of entries in
157 * the Hashtable or otherwise modify its internal structure (e.g.,
158 * rehash). This field is used to make iterators on Collection-views of
159 * the Hashtable fail-fast. (See ConcurrentModificationException).
160 */
161 private transient int modCount = 0;
162
163 /** use serialVersionUID from JDK 1.0.2 for interoperability */
164 private static final long serialVersionUID = 1421746759512286392L;
165
166 /**
167 * Constructs a new, empty hashtable with the specified initial
168 * capacity and the specified load factor.
169 *
170 * @param initialCapacity the initial capacity of the hashtable.
171 * @param loadFactor the load factor of the hashtable.
172 * @exception IllegalArgumentException if the initial capacity is less
173 * than zero, or if the load factor is nonpositive.
174 */
175 public Hashtable(int initialCapacity, float loadFactor) {
176 if (initialCapacity < 0)
177 throw new IllegalArgumentException("Illegal Capacity: "+
178 initialCapacity);
179 if (loadFactor <= 0 || Float.isNaN(loadFactor))
180 throw new IllegalArgumentException("Illegal Load: "+loadFactor);
181
182 if (initialCapacity==0)
183 initialCapacity = 1;
184 this.loadFactor = loadFactor;
185 table = new Entry[initialCapacity];
186 threshold = (int)(initialCapacity * loadFactor);
187 }
188
189 /**
190 * Constructs a new, empty hashtable with the specified initial capacity
191 * and default load factor (0.75).
192 *
193 * @param initialCapacity the initial capacity of the hashtable.
194 * @exception IllegalArgumentException if the initial capacity is less
195 * than zero.
196 */
197 public Hashtable(int initialCapacity) {
198 this(initialCapacity, 0.75f);
199 }
200
201 /**
202 * Constructs a new, empty hashtable with a default initial capacity (11)
203 * and load factor (0.75).
204 */
205 public Hashtable() {
206 this(11, 0.75f);
310 * specified value
311 * @throws NullPointerException if the value is <code>null</code>
312 * @since 1.2
313 */
314 public boolean containsValue(Object value) {
315 return contains(value);
316 }
317
318 /**
319 * Tests if the specified object is a key in this hashtable.
320 *
321 * @param key possible key
322 * @return <code>true</code> if and only if the specified object
323 * is a key in this hashtable, as determined by the
324 * <tt>equals</tt> method; <code>false</code> otherwise.
325 * @throws NullPointerException if the key is <code>null</code>
326 * @see #contains(Object)
327 */
328 public synchronized boolean containsKey(Object key) {
329 Entry tab[] = table;
330 int hash = key.hashCode();
331 int index = (hash & 0x7FFFFFFF) % tab.length;
332 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
333 if ((e.hash == hash) && e.key.equals(key)) {
334 return true;
335 }
336 }
337 return false;
338 }
339
340 /**
341 * Returns the value to which the specified key is mapped,
342 * or {@code null} if this map contains no mapping for the key.
343 *
344 * <p>More formally, if this map contains a mapping from a key
345 * {@code k} to a value {@code v} such that {@code (key.equals(k))},
346 * then this method returns {@code v}; otherwise it returns
347 * {@code null}. (There can be at most one such mapping.)
348 *
349 * @param key the key whose associated value is to be returned
350 * @return the value to which the specified key is mapped, or
351 * {@code null} if this map contains no mapping for the key
352 * @throws NullPointerException if the specified key is null
353 * @see #put(Object, Object)
354 */
355 public synchronized V get(Object key) {
356 Entry tab[] = table;
357 int hash = key.hashCode();
358 int index = (hash & 0x7FFFFFFF) % tab.length;
359 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
360 if ((e.hash == hash) && e.key.equals(key)) {
361 return e.value;
362 }
363 }
364 return null;
365 }
366
367 /**
368 * The maximum size of array to allocate.
369 * Some VMs reserve some header words in an array.
370 * Attempts to allocate larger arrays may result in
371 * OutOfMemoryError: Requested array size exceeds VM limit
372 */
373 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
374
375 /**
376 * Increases the capacity of and internally reorganizes this
377 * hashtable, in order to accommodate and access its entries more
378 * efficiently. This method is called automatically when the
379 * number of keys in the hashtable exceeds this hashtable's capacity
380 * and load factor.
381 */
382 protected void rehash() {
383 int oldCapacity = table.length;
384 Entry[] oldMap = table;
385
386 // overflow-conscious code
387 int newCapacity = (oldCapacity << 1) + 1;
388 if (newCapacity - MAX_ARRAY_SIZE > 0) {
389 if (oldCapacity == MAX_ARRAY_SIZE)
390 // Keep running with MAX_ARRAY_SIZE buckets
391 return;
392 newCapacity = MAX_ARRAY_SIZE;
393 }
394 Entry[] newMap = new Entry[newCapacity];
395
396 modCount++;
397 threshold = (int)(newCapacity * loadFactor);
398 table = newMap;
399
400 for (int i = oldCapacity ; i-- > 0 ;) {
401 for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
402 Entry<K,V> e = old;
403 old = old.next;
404
405 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
406 e.next = newMap[index];
407 newMap[index] = e;
408 }
409 }
410 }
411
412 /**
413 * Maps the specified <code>key</code> to the specified
414 * <code>value</code> in this hashtable. Neither the key nor the
415 * value can be <code>null</code>. <p>
416 *
417 * The value can be retrieved by calling the <code>get</code> method
418 * with a key that is equal to the original key.
419 *
420 * @param key the hashtable key
421 * @param value the value
422 * @return the previous value of the specified key in this hashtable,
423 * or <code>null</code> if it did not have one
424 * @exception NullPointerException if the key or value is
425 * <code>null</code>
426 * @see Object#equals(Object)
427 * @see #get(Object)
428 */
429 public synchronized V put(K key, V value) {
430 // Make sure the value is not null
431 if (value == null) {
432 throw new NullPointerException();
433 }
434
435 // Makes sure the key is not already in the hashtable.
436 Entry tab[] = table;
437 int hash = key.hashCode();
438 int index = (hash & 0x7FFFFFFF) % tab.length;
439 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
440 if ((e.hash == hash) && e.key.equals(key)) {
441 V old = e.value;
442 e.value = value;
443 return old;
444 }
445 }
446
447 modCount++;
448 if (count >= threshold) {
449 // Rehash the table if the threshold is exceeded
450 rehash();
451
452 tab = table;
453 index = (hash & 0x7FFFFFFF) % tab.length;
454 }
455
456 // Creates the new entry.
457 Entry<K,V> e = tab[index];
458 tab[index] = new Entry<>(hash, key, value, e);
459 count++;
460 return null;
461 }
462
463 /**
464 * Removes the key (and its corresponding value) from this
465 * hashtable. This method does nothing if the key is not in the hashtable.
466 *
467 * @param key the key that needs to be removed
468 * @return the value to which the key had been mapped in this hashtable,
469 * or <code>null</code> if the key did not have a mapping
470 * @throws NullPointerException if the key is <code>null</code>
471 */
472 public synchronized V remove(Object key) {
473 Entry tab[] = table;
474 int hash = key.hashCode();
475 int index = (hash & 0x7FFFFFFF) % tab.length;
476 for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
477 if ((e.hash == hash) && e.key.equals(key)) {
478 modCount++;
479 if (prev != null) {
480 prev.next = e.next;
481 } else {
482 tab[index] = e.next;
483 }
484 count--;
485 V oldValue = e.value;
486 e.value = null;
487 return oldValue;
488 }
489 }
490 return null;
491 }
492
493 /**
494 * Copies all of the mappings from the specified map to this hashtable.
661 if (entrySet==null)
662 entrySet = Collections.synchronizedSet(new EntrySet(), this);
663 return entrySet;
664 }
665
666 private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
667 public Iterator<Map.Entry<K,V>> iterator() {
668 return getIterator(ENTRIES);
669 }
670
671 public boolean add(Map.Entry<K,V> o) {
672 return super.add(o);
673 }
674
675 public boolean contains(Object o) {
676 if (!(o instanceof Map.Entry))
677 return false;
678 Map.Entry entry = (Map.Entry)o;
679 Object key = entry.getKey();
680 Entry[] tab = table;
681 int hash = key.hashCode();
682 int index = (hash & 0x7FFFFFFF) % tab.length;
683
684 for (Entry e = tab[index]; e != null; e = e.next)
685 if (e.hash==hash && e.equals(entry))
686 return true;
687 return false;
688 }
689
690 public boolean remove(Object o) {
691 if (!(o instanceof Map.Entry))
692 return false;
693 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
694 K key = entry.getKey();
695 Entry[] tab = table;
696 int hash = key.hashCode();
697 int index = (hash & 0x7FFFFFFF) % tab.length;
698
699 for (Entry<K,V> e = tab[index], prev = null; e != null;
700 prev = e, e = e.next) {
701 if (e.hash==hash && e.equals(entry)) {
702 modCount++;
703 if (prev != null)
704 prev.next = e.next;
705 else
706 tab[index] = e.next;
707
708 count--;
709 e.value = null;
710 return true;
711 }
712 }
713 return false;
714 }
715
716 public int size() {
810 * @see Map#hashCode()
811 * @since 1.2
812 */
813 public synchronized int hashCode() {
814 /*
815 * This code detects the recursion caused by computing the hash code
816 * of a self-referential hash table and prevents the stack overflow
817 * that would otherwise result. This allows certain 1.1-era
818 * applets with self-referential hash tables to work. This code
819 * abuses the loadFactor field to do double-duty as a hashCode
820 * in progress flag, so as not to worsen the space performance.
821 * A negative load factor indicates that hash code computation is
822 * in progress.
823 */
824 int h = 0;
825 if (count == 0 || loadFactor < 0)
826 return h; // Returns zero
827
828 loadFactor = -loadFactor; // Mark hashCode computation in progress
829 Entry[] tab = table;
830 for (int i = 0; i < tab.length; i++)
831 for (Entry e = tab[i]; e != null; e = e.next)
832 h += e.key.hashCode() ^ e.value.hashCode();
833 loadFactor = -loadFactor; // Mark hashCode computation complete
834
835 return h;
836 }
837
838 /**
839 * Save the state of the Hashtable to a stream (i.e., serialize it).
840 *
841 * @serialData The <i>capacity</i> of the Hashtable (the length of the
842 * bucket array) is emitted (int), followed by the
843 * <i>size</i> of the Hashtable (the number of key-value
844 * mappings), followed by the key (Object) and value (Object)
845 * for each key-value mapping represented by the Hashtable
846 * The key-value mappings are emitted in no particular order.
847 */
848 private void writeObject(java.io.ObjectOutputStream s)
849 throws IOException {
850 Entry<Object, Object> entryStack = null;
851
852 synchronized (this) {
853 // Write out the length, threshold, loadfactor
854 s.defaultWriteObject();
855
856 // Write out length, count of elements
857 s.writeInt(table.length);
858 s.writeInt(count);
859
860 // Stack copies of the entries in the table
861 for (int index = 0; index < table.length; index++) {
862 Entry entry = table[index];
863
864 while (entry != null) {
865 entryStack =
866 new Entry<>(0, entry.key, entry.value, entryStack);
867 entry = entry.next;
868 }
869 }
870 }
871
872 // Write out the key/value objects from the stacked entries
873 while (entryStack != null) {
874 s.writeObject(entryStack.key);
875 s.writeObject(entryStack.value);
876 entryStack = entryStack.next;
877 }
878 }
879
880 /**
881 * Reconstitute the Hashtable from a stream (i.e., deserialize it).
882 */
883 private void readObject(java.io.ObjectInputStream s)
884 throws IOException, ClassNotFoundException
885 {
886 // Read in the length, threshold, and loadfactor
887 s.defaultReadObject();
888
889 // Read the original length of the array and number of elements
890 int origlength = s.readInt();
891 int elements = s.readInt();
892
893 // Compute new size with a bit of room 5% to grow but
894 // no larger than the original size. Make the length
895 // odd if it's large enough, this helps distribute the entries.
896 // Guard against the length ending up zero, that's not valid.
897 int length = (int)(elements * loadFactor) + (elements / 20) + 3;
898 if (length > elements && (length & 1) == 0)
899 length--;
900 if (origlength > 0 && length > origlength)
901 length = origlength;
902
903 Entry[] table = new Entry[length];
904 count = 0;
905
906 // Read the number of elements and then all the key/value objects
907 for (; elements > 0; elements--) {
908 K key = (K)s.readObject();
909 V value = (V)s.readObject();
910 // synch could be eliminated for performance
911 reconstitutionPut(table, key, value);
912 }
913 this.table = table;
914 }
915
916 /**
917 * The put method used by readObject. This is provided because put
918 * is overridable and should not be called in readObject since the
919 * subclass will not yet be initialized.
920 *
921 * <p>This differs from the regular put method in several ways. No
922 * checking for rehashing is necessary since the number of elements
923 * initially in the table is known. The modCount is not incremented
924 * because we are creating a new instance. Also, no return value
925 * is needed.
926 */
927 private void reconstitutionPut(Entry[] tab, K key, V value)
928 throws StreamCorruptedException
929 {
930 if (value == null) {
931 throw new java.io.StreamCorruptedException();
932 }
933 // Makes sure the key is not already in the hashtable.
934 // This should not happen in deserialized version.
935 int hash = key.hashCode();
936 int index = (hash & 0x7FFFFFFF) % tab.length;
937 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
938 if ((e.hash == hash) && e.key.equals(key)) {
939 throw new java.io.StreamCorruptedException();
940 }
941 }
942 // Creates the new entry.
943 Entry<K,V> e = tab[index];
944 tab[index] = new Entry<>(hash, key, value, e);
945 count++;
946 }
947
948 /**
949 * Hashtable collision list.
950 */
951 private static class Entry<K,V> implements Map.Entry<K,V> {
952 int hash;
953 K key;
954 V value;
955 Entry<K,V> next;
956
957 protected Entry(int hash, K key, V value, Entry<K,V> next) {
958 this.hash = hash;
959 this.key = key;
960 this.value = value;
961 this.next = next;
962 }
963
964 protected Object clone() {
965 return new Entry<>(hash, key, value,
966 (next==null ? null : (Entry<K,V>) next.clone()));
967 }
968
969 // Map.Entry Ops
971 public K getKey() {
972 return key;
973 }
974
975 public V getValue() {
976 return value;
977 }
978
979 public V setValue(V value) {
980 if (value == null)
981 throw new NullPointerException();
982
983 V oldValue = this.value;
984 this.value = value;
985 return oldValue;
986 }
987
988 public boolean equals(Object o) {
989 if (!(o instanceof Map.Entry))
990 return false;
991 Map.Entry e = (Map.Entry)o;
992
993 return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
994 (value==null ? e.getValue()==null : value.equals(e.getValue()));
995 }
996
997 public int hashCode() {
998 return hash ^ (value==null ? 0 : value.hashCode());
999 }
1000
1001 public String toString() {
1002 return key.toString()+"="+value.toString();
1003 }
1004 }
1005
1006 // Types of Enumerations/Iterations
1007 private static final int KEYS = 0;
1008 private static final int VALUES = 1;
1009 private static final int ENTRIES = 2;
1010
1011 /**
1012 * A hashtable enumerator class. This class implements both the
1013 * Enumeration and Iterator interfaces, but individual instances
1014 * can be created with the Iterator methods disabled. This is necessary
1015 * to avoid unintentionally increasing the capabilities granted a user
1016 * by passing an Enumeration.
1017 */
1018 private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
|
112 *
113 * @author Arthur van Hoff
114 * @author Josh Bloch
115 * @author Neal Gafter
116 * @see Object#equals(java.lang.Object)
117 * @see Object#hashCode()
118 * @see Hashtable#rehash()
119 * @see Collection
120 * @see Map
121 * @see HashMap
122 * @see TreeMap
123 * @since JDK1.0
124 */
125 public class Hashtable<K,V>
126 extends Dictionary<K,V>
127 implements Map<K,V>, Cloneable, java.io.Serializable {
128
129 /**
130 * The hash table data.
131 */
132 private transient Entry<K,V>[] table;
133
134 /**
135 * The total number of entries in the hash table.
136 */
137 private transient int count;
138
139 /**
140 * The table is rehashed when its size exceeds this threshold. (The
141 * value of this field is (int)(capacity * loadFactor).)
142 *
143 * @serial
144 */
145 private int threshold;
146
147 /**
148 * The load factor for the hashtable.
149 *
150 * @serial
151 */
152 private float loadFactor;
153
154 /**
155 * The number of times this Hashtable has been structurally modified
156 * Structural modifications are those that change the number of entries in
157 * the Hashtable or otherwise modify its internal structure (e.g.,
158 * rehash). This field is used to make iterators on Collection-views of
159 * the Hashtable fail-fast. (See ConcurrentModificationException).
160 */
161 private transient int modCount = 0;
162
163 /** use serialVersionUID from JDK 1.0.2 for interoperability */
164 private static final long serialVersionUID = 1421746759512286392L;
165
166 /**
167 * The default threshold of capacity above which alternate hashing is used.
168 * Alternative hashing reduces the incidence of collisions due to weak hash
169 * code calculation.
170 * <p/>
171 * This value may be overridden by defining the system property
172 * {@code java.util.althashing.threshold}. A property value of {@code 1}
173 * forces alternative hashing to be used at all times whereas
174 * {@code 2147483648 } ({@code Integer.MAX_VALUE}) value ensures that
175 * alternative hashing is never used.
176 */
177 static final int ALTERNATE_HASHING_THRESHOLD_DEFAULT = 0;
178
179 /**
180 * holds values which can't be initialized until after VM is booted.
181 */
182 private static class Holder {
183
184 /**
185 * Table capacity above which to switch to use alternate hashing.
186 */
187 static final int ALTERNATE_HASHING_THRESHOLD;
188
189 static {
190 String altThreshold = java.security.AccessController.doPrivileged(
191 new sun.security.action.GetPropertyAction(
192 "jdk.map.althashing.threshold"));
193
194 int threshold;
195 try {
196 threshold = (null != altThreshold)
197 ? Integer.parseInt(altThreshold)
198 : 1;
199
200 if(threshold == -1) {
201 threshold = Integer.MAX_VALUE;
202 }
203
204 if(threshold < 0) {
205 throw new IllegalArgumentException("value must be positive integer.");
206 }
207 } catch(IllegalArgumentException failed) {
208 throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
209 }
210
211 ALTERNATE_HASHING_THRESHOLD = threshold;
212 }
213 }
214
215 /**
216 * If {@code true} then perform alternate hashing to reduce the incidence of
217 * collisions due to weak hash code calculation.
218 */
219 transient boolean useAltHashing;
220
221 // Unsafe mechanics
222 private static final sun.misc.Unsafe UNSAFE;
223 private static final long HASHSEED_OFFSET;
224
225 static {
226 try {
227 UNSAFE = sun.misc.Unsafe.getUnsafe();
228 HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
229 Hashtable.class.getDeclaredField("hashSeed"));
230 } catch (NoSuchFieldException | SecurityException e) {
231 throw new Error("Failed to record hashSeed offset", e);
232 }
233 }
234
235 /**
236 * A randomizing value associated with this instance that is applied to
237 * hash code of keys to make hash collisions harder to find.
238 */
239 transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);
240
241 private int hash(Object k) {
242 if (useAltHashing) {
243 int h = hashSeed;
244 if (k.getClass() == String.class) {
245 return h ^ sun.misc.Hashing.stringHash32((String) k);
246 } else {
247 h ^= k.hashCode();
248
249 // This function ensures that hashCodes that differ only by
250 // constant multiples at each bit position have a bounded
251 // number of collisions (approximately 8 at default load factor).
252 h ^= (h >>> 20) ^ (h >>> 12);
253 return h ^ (h >>> 7) ^ (h >>> 4);
254 }
255 } else {
256 return k.hashCode();
257 }
258 }
259
260 /**
261 * Constructs a new, empty hashtable with the specified initial
262 * capacity and the specified load factor.
263 *
264 * @param initialCapacity the initial capacity of the hashtable.
265 * @param loadFactor the load factor of the hashtable.
266 * @exception IllegalArgumentException if the initial capacity is less
267 * than zero, or if the load factor is nonpositive.
268 */
269 public Hashtable(int initialCapacity, float loadFactor) {
270 if (initialCapacity < 0)
271 throw new IllegalArgumentException("Illegal Capacity: "+
272 initialCapacity);
273 if (loadFactor <= 0 || Float.isNaN(loadFactor))
274 throw new IllegalArgumentException("Illegal Load: "+loadFactor);
275
276 if (initialCapacity==0)
277 initialCapacity = 1;
278 this.loadFactor = loadFactor;
279 table = new Entry[initialCapacity];
280 threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
281 useAltHashing = sun.misc.VM.isBooted() &&
282 (initialCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
283 }
284
285 /**
286 * Constructs a new, empty hashtable with the specified initial capacity
287 * and default load factor (0.75).
288 *
289 * @param initialCapacity the initial capacity of the hashtable.
290 * @exception IllegalArgumentException if the initial capacity is less
291 * than zero.
292 */
293 public Hashtable(int initialCapacity) {
294 this(initialCapacity, 0.75f);
295 }
296
297 /**
298 * Constructs a new, empty hashtable with a default initial capacity (11)
299 * and load factor (0.75).
300 */
301 public Hashtable() {
302 this(11, 0.75f);
406 * specified value
407 * @throws NullPointerException if the value is <code>null</code>
408 * @since 1.2
409 */
410 public boolean containsValue(Object value) {
411 return contains(value);
412 }
413
414 /**
415 * Tests if the specified object is a key in this hashtable.
416 *
417 * @param key possible key
418 * @return <code>true</code> if and only if the specified object
419 * is a key in this hashtable, as determined by the
420 * <tt>equals</tt> method; <code>false</code> otherwise.
421 * @throws NullPointerException if the key is <code>null</code>
422 * @see #contains(Object)
423 */
424 public synchronized boolean containsKey(Object key) {
425 Entry tab[] = table;
426 int hash = hash(key);
427 int index = (hash & 0x7FFFFFFF) % tab.length;
428 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
429 if ((e.hash == hash) && e.key.equals(key)) {
430 return true;
431 }
432 }
433 return false;
434 }
435
436 /**
437 * Returns the value to which the specified key is mapped,
438 * or {@code null} if this map contains no mapping for the key.
439 *
440 * <p>More formally, if this map contains a mapping from a key
441 * {@code k} to a value {@code v} such that {@code (key.equals(k))},
442 * then this method returns {@code v}; otherwise it returns
443 * {@code null}. (There can be at most one such mapping.)
444 *
445 * @param key the key whose associated value is to be returned
446 * @return the value to which the specified key is mapped, or
447 * {@code null} if this map contains no mapping for the key
448 * @throws NullPointerException if the specified key is null
449 * @see #put(Object, Object)
450 */
451 public synchronized V get(Object key) {
452 Entry tab[] = table;
453 int hash = hash(key);
454 int index = (hash & 0x7FFFFFFF) % tab.length;
455 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
456 if ((e.hash == hash) && e.key.equals(key)) {
457 return e.value;
458 }
459 }
460 return null;
461 }
462
463 /**
464 * The maximum size of array to allocate.
465 * Some VMs reserve some header words in an array.
466 * Attempts to allocate larger arrays may result in
467 * OutOfMemoryError: Requested array size exceeds VM limit
468 */
469 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
470
471 /**
472 * Increases the capacity of and internally reorganizes this
473 * hashtable, in order to accommodate and access its entries more
474 * efficiently. This method is called automatically when the
475 * number of keys in the hashtable exceeds this hashtable's capacity
476 * and load factor.
477 */
478 protected void rehash() {
479 int oldCapacity = table.length;
480 Entry<K,V>[] oldMap = table;
481
482 // overflow-conscious code
483 int newCapacity = (oldCapacity << 1) + 1;
484 if (newCapacity - MAX_ARRAY_SIZE > 0) {
485 if (oldCapacity == MAX_ARRAY_SIZE)
486 // Keep running with MAX_ARRAY_SIZE buckets
487 return;
488 newCapacity = MAX_ARRAY_SIZE;
489 }
490 Entry<K,V>[] newMap = new Entry[newCapacity];
491
492 modCount++;
493 threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
494 boolean currentAltHashing = useAltHashing;
495 useAltHashing = sun.misc.VM.isBooted() &&
496 (newCapacity >= Holder.ALTERNATE_HASHING_THRESHOLD);
497 boolean rehash = currentAltHashing ^ useAltHashing;
498
499 table = newMap;
500
501 for (int i = oldCapacity ; i-- > 0 ;) {
502 for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
503 Entry<K,V> e = old;
504 old = old.next;
505
506 if(rehash) {
507 e.hash = hash(e.key);
508 }
509 int index = (e.hash & 0x7FFFFFFF) % newCapacity;
510 e.next = newMap[index];
511 newMap[index] = e;
512 }
513 }
514 }
515
516 /**
517 * Maps the specified <code>key</code> to the specified
518 * <code>value</code> in this hashtable. Neither the key nor the
519 * value can be <code>null</code>. <p>
520 *
521 * The value can be retrieved by calling the <code>get</code> method
522 * with a key that is equal to the original key.
523 *
524 * @param key the hashtable key
525 * @param value the value
526 * @return the previous value of the specified key in this hashtable,
527 * or <code>null</code> if it did not have one
528 * @exception NullPointerException if the key or value is
529 * <code>null</code>
530 * @see Object#equals(Object)
531 * @see #get(Object)
532 */
533 public synchronized V put(K key, V value) {
534 // Make sure the value is not null
535 if (value == null) {
536 throw new NullPointerException();
537 }
538
539 // Makes sure the key is not already in the hashtable.
540 Entry tab[] = table;
541 int hash = hash(key);
542 int index = (hash & 0x7FFFFFFF) % tab.length;
543 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
544 if ((e.hash == hash) && e.key.equals(key)) {
545 V old = e.value;
546 e.value = value;
547 return old;
548 }
549 }
550
551 modCount++;
552 if (count >= threshold) {
553 // Rehash the table if the threshold is exceeded
554 rehash();
555
556 tab = table;
557 hash = hash(key);
558 index = (hash & 0x7FFFFFFF) % tab.length;
559 }
560
561 // Creates the new entry.
562 Entry<K,V> e = tab[index];
563 tab[index] = new Entry<>(hash, key, value, e);
564 count++;
565 return null;
566 }
567
568 /**
569 * Removes the key (and its corresponding value) from this
570 * hashtable. This method does nothing if the key is not in the hashtable.
571 *
572 * @param key the key that needs to be removed
573 * @return the value to which the key had been mapped in this hashtable,
574 * or <code>null</code> if the key did not have a mapping
575 * @throws NullPointerException if the key is <code>null</code>
576 */
577 public synchronized V remove(Object key) {
578 Entry tab[] = table;
579 int hash = hash(key);
580 int index = (hash & 0x7FFFFFFF) % tab.length;
581 for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
582 if ((e.hash == hash) && e.key.equals(key)) {
583 modCount++;
584 if (prev != null) {
585 prev.next = e.next;
586 } else {
587 tab[index] = e.next;
588 }
589 count--;
590 V oldValue = e.value;
591 e.value = null;
592 return oldValue;
593 }
594 }
595 return null;
596 }
597
598 /**
599 * Copies all of the mappings from the specified map to this hashtable.
766 if (entrySet==null)
767 entrySet = Collections.synchronizedSet(new EntrySet(), this);
768 return entrySet;
769 }
770
771 private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
772 public Iterator<Map.Entry<K,V>> iterator() {
773 return getIterator(ENTRIES);
774 }
775
776 public boolean add(Map.Entry<K,V> o) {
777 return super.add(o);
778 }
779
780 public boolean contains(Object o) {
781 if (!(o instanceof Map.Entry))
782 return false;
783 Map.Entry entry = (Map.Entry)o;
784 Object key = entry.getKey();
785 Entry[] tab = table;
786 int hash = hash(key);
787 int index = (hash & 0x7FFFFFFF) % tab.length;
788
789 for (Entry e = tab[index]; e != null; e = e.next)
790 if (e.hash==hash && e.equals(entry))
791 return true;
792 return false;
793 }
794
795 public boolean remove(Object o) {
796 if (!(o instanceof Map.Entry))
797 return false;
798 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
799 K key = entry.getKey();
800 Entry[] tab = table;
801 int hash = hash(key);
802 int index = (hash & 0x7FFFFFFF) % tab.length;
803
804 for (Entry<K,V> e = tab[index], prev = null; e != null;
805 prev = e, e = e.next) {
806 if (e.hash==hash && e.equals(entry)) {
807 modCount++;
808 if (prev != null)
809 prev.next = e.next;
810 else
811 tab[index] = e.next;
812
813 count--;
814 e.value = null;
815 return true;
816 }
817 }
818 return false;
819 }
820
821 public int size() {
915 * @see Map#hashCode()
916 * @since 1.2
917 */
918 public synchronized int hashCode() {
919 /*
920 * This code detects the recursion caused by computing the hash code
921 * of a self-referential hash table and prevents the stack overflow
922 * that would otherwise result. This allows certain 1.1-era
923 * applets with self-referential hash tables to work. This code
924 * abuses the loadFactor field to do double-duty as a hashCode
925 * in progress flag, so as not to worsen the space performance.
926 * A negative load factor indicates that hash code computation is
927 * in progress.
928 */
929 int h = 0;
930 if (count == 0 || loadFactor < 0)
931 return h; // Returns zero
932
933 loadFactor = -loadFactor; // Mark hashCode computation in progress
934 Entry[] tab = table;
935 for (Entry<K,V> entry : tab)
936 while (entry != null) {
937 h += entry.hashCode();
938 entry = entry.next;
939 }
940 loadFactor = -loadFactor; // Mark hashCode computation complete
941
942 return h;
943 }
944
945 /**
946 * Save the state of the Hashtable to a stream (i.e., serialize it).
947 *
948 * @serialData The <i>capacity</i> of the Hashtable (the length of the
949 * bucket array) is emitted (int), followed by the
950 * <i>size</i> of the Hashtable (the number of key-value
951 * mappings), followed by the key (Object) and value (Object)
952 * for each key-value mapping represented by the Hashtable
953 * The key-value mappings are emitted in no particular order.
954 */
955 private void writeObject(java.io.ObjectOutputStream s)
956 throws IOException {
957 Entry<K, V> entryStack = null;
958
959 synchronized (this) {
960 // Write out the length, threshold, loadfactor
961 s.defaultWriteObject();
962
963 // Write out length, count of elements
964 s.writeInt(table.length);
965 s.writeInt(count);
966
967 // Stack copies of the entries in the table
968 for (int index = 0; index < table.length; index++) {
969 Entry<K,V> entry = table[index];
970
971 while (entry != null) {
972 entryStack =
973 new Entry<>(0, entry.key, entry.value, entryStack);
974 entry = entry.next;
975 }
976 }
977 }
978
979 // Write out the key/value objects from the stacked entries
980 while (entryStack != null) {
981 s.writeObject(entryStack.key);
982 s.writeObject(entryStack.value);
983 entryStack = entryStack.next;
984 }
985 }
986
987 /**
988 * Reconstitute the Hashtable from a stream (i.e., deserialize it).
989 */
990 private void readObject(java.io.ObjectInputStream s)
991 throws IOException, ClassNotFoundException
992 {
993 // Read in the length, threshold, and loadfactor
994 s.defaultReadObject();
995
996 // set hashSeed
997 UNSAFE.putIntVolatile(this, HASHSEED_OFFSET,
998 sun.misc.Hashing.randomHashSeed(this));
999
1000 // Read the original length of the array and number of elements
1001 int origlength = s.readInt();
1002 int elements = s.readInt();
1003
1004 // Compute new size with a bit of room 5% to grow but
1005 // no larger than the original size. Make the length
1006 // odd if it's large enough, this helps distribute the entries.
1007 // Guard against the length ending up zero, that's not valid.
1008 int length = (int)(elements * loadFactor) + (elements / 20) + 3;
1009 if (length > elements && (length & 1) == 0)
1010 length--;
1011 if (origlength > 0 && length > origlength)
1012 length = origlength;
1013
1014 Entry<K,V>[] table = new Entry[length];
1015 threshold = (int) Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
1016 count = 0;
1017 useAltHashing = sun.misc.VM.isBooted() &&
1018 (length >= Holder.ALTERNATE_HASHING_THRESHOLD);
1019
1020 // Read the number of elements and then all the key/value objects
1021 for (; elements > 0; elements--) {
1022 K key = (K)s.readObject();
1023 V value = (V)s.readObject();
1024 // synch could be eliminated for performance
1025 reconstitutionPut(table, key, value);
1026 }
1027 this.table = table;
1028 }
1029
1030 /**
1031 * The put method used by readObject. This is provided because put
1032 * is overridable and should not be called in readObject since the
1033 * subclass will not yet be initialized.
1034 *
1035 * <p>This differs from the regular put method in several ways. No
1036 * checking for rehashing is necessary since the number of elements
1037 * initially in the table is known. The modCount is not incremented
1038 * because we are creating a new instance. Also, no return value
1039 * is needed.
1040 */
1041 private void reconstitutionPut(Entry<K,V>[] tab, K key, V value)
1042 throws StreamCorruptedException
1043 {
1044 if (value == null) {
1045 throw new java.io.StreamCorruptedException();
1046 }
1047 // Makes sure the key is not already in the hashtable.
1048 // This should not happen in deserialized version.
1049 int hash = hash(key);
1050 int index = (hash & 0x7FFFFFFF) % tab.length;
1051 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
1052 if ((e.hash == hash) && e.key.equals(key)) {
1053 throw new java.io.StreamCorruptedException();
1054 }
1055 }
1056 // Creates the new entry.
1057 Entry<K,V> e = tab[index];
1058 tab[index] = new Entry<>(hash, key, value, e);
1059 count++;
1060 }
1061
1062 /**
1063 * Hashtable bucket collision list entry
1064 */
1065 private static class Entry<K,V> implements Map.Entry<K,V> {
1066 int hash;
1067 K key;
1068 V value;
1069 Entry<K,V> next;
1070
1071 protected Entry(int hash, K key, V value, Entry<K,V> next) {
1072 this.hash = hash;
1073 this.key = key;
1074 this.value = value;
1075 this.next = next;
1076 }
1077
1078 protected Object clone() {
1079 return new Entry<>(hash, key, value,
1080 (next==null ? null : (Entry<K,V>) next.clone()));
1081 }
1082
1083 // Map.Entry Ops
1085 public K getKey() {
1086 return key;
1087 }
1088
1089 public V getValue() {
1090 return value;
1091 }
1092
1093 public V setValue(V value) {
1094 if (value == null)
1095 throw new NullPointerException();
1096
1097 V oldValue = this.value;
1098 this.value = value;
1099 return oldValue;
1100 }
1101
1102 public boolean equals(Object o) {
1103 if (!(o instanceof Map.Entry))
1104 return false;
1105 Map.Entry<?,?> e = (Map.Entry)o;
1106
1107 return key.equals(e.getKey()) && value.equals(e.getValue());
1108 }
1109
1110 public int hashCode() {
1111 return hash ^ value.hashCode();
1112 }
1113
1114 public String toString() {
1115 return key.toString()+"="+value.toString();
1116 }
1117 }
1118
1119 // Types of Enumerations/Iterations
1120 private static final int KEYS = 0;
1121 private static final int VALUES = 1;
1122 private static final int ENTRIES = 2;
1123
1124 /**
1125 * A hashtable enumerator class. This class implements both the
1126 * Enumeration and Iterator interfaces, but individual instances
1127 * can be created with the Iterator methods disabled. This is necessary
1128 * to avoid unintentionally increasing the capabilities granted a user
1129 * by passing an Enumeration.
1130 */
1131 private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
|