1. /*
  2. * @(#)Hashtable.java 1.105 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util;
  8. import java.io.*;
  9. /**
  10. * This class implements a hashtable, which maps keys to values. Any
  11. * non-<code>null</code> object can be used as a key or as a value. <p>
  12. *
  13. * To successfully store and retrieve objects from a hashtable, the
  14. * objects used as keys must implement the <code>hashCode</code>
  15. * method and the <code>equals</code> method. <p>
  16. *
  17. * An instance of <code>Hashtable</code> has two parameters that affect its
  18. * performance: <i>initial capacity</i> and <i>load factor</i>. The
  19. * <i>capacity</i> is the number of <i>buckets</i> in the hash table, and the
  20. * <i>initial capacity</i> is simply the capacity at the time the hash table
  21. * is created. Note that the hash table is <i>open</i>: in the case of a "hash
  22. * collision", a single bucket stores multiple entries, which must be searched
  23. * sequentially. The <i>load factor</i> is a measure of how full the hash
  24. * table is allowed to get before its capacity is automatically increased.
  25. * The initial capacity and load factor parameters are merely hints to
  26. * the implementation. The exact details as to when and whether the rehash
  27. * method is invoked are implementation-dependent.<p>
  28. *
  29. * Generally, the default load factor (.75) offers a good tradeoff between
  30. * time and space costs. Higher values decrease the space overhead but
  31. * increase the time cost to look up an entry (which is reflected in most
  32. * <tt>Hashtable</tt> operations, including <tt>get</tt> and <tt>put</tt>).<p>
  33. *
  34. * The initial capacity controls a tradeoff between wasted space and the
  35. * need for <code>rehash</code> operations, which are time-consuming.
  36. * No <code>rehash</code> operations will <i>ever</i> occur if the initial
  37. * capacity is greater than the maximum number of entries the
  38. * <tt>Hashtable</tt> will contain divided by its load factor. However,
  39. * setting the initial capacity too high can waste space.<p>
  40. *
  41. * If many entries are to be made into a <code>Hashtable</code>,
  42. * creating it with a sufficiently large capacity may allow the
  43. * entries to be inserted more efficiently than letting it perform
  44. * automatic rehashing as needed to grow the table. <p>
  45. *
  46. * This example creates a hashtable of numbers. It uses the names of
  47. * the numbers as keys:
  48. * <p><blockquote><pre>
  49. * Hashtable numbers = new Hashtable();
  50. * numbers.put("one", new Integer(1));
  51. * numbers.put("two", new Integer(2));
  52. * numbers.put("three", new Integer(3));
  53. * </pre></blockquote>
  54. * <p>
  55. * To retrieve a number, use the following code:
  56. * <p><blockquote><pre>
  57. * Integer n = (Integer)numbers.get("two");
  58. * if (n != null) {
  59. * System.out.println("two = " + n);
  60. * }
  61. * </pre></blockquote>
  62. * <p>
  63. * As of the Java 2 platform v1.2, this class has been retrofitted to
  64. * implement Map, so that it becomes a part of Java's collection framework.
  65. * Unlike the new collection implementations, Hashtable is synchronized.<p>
  66. *
  67. * The Iterators returned by the iterator and listIterator methods
  68. * of the Collections returned by all of Hashtable's "collection view methods"
  69. * are <em>fail-fast</em>: if the Hashtable is structurally modified
  70. * at any time after the Iterator is created, in any way except through the
  71. * Iterator's own remove or add methods, the Iterator will throw a
  72. * ConcurrentModificationException. Thus, in the face of concurrent
  73. * modification, the Iterator fails quickly and cleanly, rather than risking
  74. * arbitrary, non-deterministic behavior at an undetermined time in the future.
  75. * The Enumerations returned by Hashtable's keys and values methods are
  76. * <em>not</em> fail-fast.
  77. *
  78. * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  79. * as it is, generally speaking, impossible to make any hard guarantees in the
  80. * presence of unsynchronized concurrent modification. Fail-fast iterators
  81. * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
  82. * Therefore, it would be wrong to write a program that depended on this
  83. * exception for its correctness: <i>the fail-fast behavior of iterators
  84. * should be used only to detect bugs.</i><p>
  85. *
  86. * This class is a member of the
  87. * <a href="{@docRoot}/../guide/collections/index.html">
  88. * Java Collections Framework</a>.
  89. *
  90. * @author Arthur van Hoff
  91. * @author Josh Bloch
  92. * @author Neal Gafter
  93. * @version 1.105, 12/19/03
  94. * @see Object#equals(java.lang.Object)
  95. * @see Object#hashCode()
  96. * @see Hashtable#rehash()
  97. * @see Collection
  98. * @see Map
  99. * @see HashMap
  100. * @see TreeMap
  101. * @since JDK1.0
  102. */
  103. public class Hashtable<K,V>
  104. extends Dictionary<K,V>
  105. implements Map<K,V>, Cloneable, java.io.Serializable {
  106. /**
  107. * The hash table data.
  108. */
  109. private transient Entry[] table;
  110. /**
  111. * The total number of entries in the hash table.
  112. */
  113. private transient int count;
  114. /**
  115. * The table is rehashed when its size exceeds this threshold. (The
  116. * value of this field is (int)(capacity * loadFactor).)
  117. *
  118. * @serial
  119. */
  120. private int threshold;
  121. /**
  122. * The load factor for the hashtable.
  123. *
  124. * @serial
  125. */
  126. private float loadFactor;
  127. /**
  128. * The number of times this Hashtable has been structurally modified
  129. * Structural modifications are those that change the number of entries in
  130. * the Hashtable or otherwise modify its internal structure (e.g.,
  131. * rehash). This field is used to make iterators on Collection-views of
  132. * the Hashtable fail-fast. (See ConcurrentModificationException).
  133. */
  134. private transient int modCount = 0;
  135. /** use serialVersionUID from JDK 1.0.2 for interoperability */
  136. private static final long serialVersionUID = 1421746759512286392L;
  137. /**
  138. * Constructs a new, empty hashtable with the specified initial
  139. * capacity and the specified load factor.
  140. *
  141. * @param initialCapacity the initial capacity of the hashtable.
  142. * @param loadFactor the load factor of the hashtable.
  143. * @exception IllegalArgumentException if the initial capacity is less
  144. * than zero, or if the load factor is nonpositive.
  145. */
  146. public Hashtable(int initialCapacity, float loadFactor) {
  147. if (initialCapacity < 0)
  148. throw new IllegalArgumentException("Illegal Capacity: "+
  149. initialCapacity);
  150. if (loadFactor <= 0 || Float.isNaN(loadFactor))
  151. throw new IllegalArgumentException("Illegal Load: "+loadFactor);
  152. if (initialCapacity==0)
  153. initialCapacity = 1;
  154. this.loadFactor = loadFactor;
  155. table = new Entry[initialCapacity];
  156. threshold = (int)(initialCapacity * loadFactor);
  157. }
  158. /**
  159. * Constructs a new, empty hashtable with the specified initial capacity
  160. * and default load factor, which is <tt>0.75</tt>.
  161. *
  162. * @param initialCapacity the initial capacity of the hashtable.
  163. * @exception IllegalArgumentException if the initial capacity is less
  164. * than zero.
  165. */
  166. public Hashtable(int initialCapacity) {
  167. this(initialCapacity, 0.75f);
  168. }
  169. /**
  170. * Constructs a new, empty hashtable with a default initial capacity (11)
  171. * and load factor, which is <tt>0.75</tt>.
  172. */
  173. public Hashtable() {
  174. this(11, 0.75f);
  175. }
  176. /**
  177. * Constructs a new hashtable with the same mappings as the given
  178. * Map. The hashtable is created with an initial capacity sufficient to
  179. * hold the mappings in the given Map and a default load factor, which is
  180. * <tt>0.75</tt>.
  181. *
  182. * @param t the map whose mappings are to be placed in this map.
  183. * @throws NullPointerException if the specified map is null.
  184. * @since 1.2
  185. */
  186. public Hashtable(Map<? extends K, ? extends V> t) {
  187. this(Math.max(2*t.size(), 11), 0.75f);
  188. putAll(t);
  189. }
  190. /**
  191. * Returns the number of keys in this hashtable.
  192. *
  193. * @return the number of keys in this hashtable.
  194. */
  195. public synchronized int size() {
  196. return count;
  197. }
  198. /**
  199. * Tests if this hashtable maps no keys to values.
  200. *
  201. * @return <code>true</code> if this hashtable maps no keys to values;
  202. * <code>false</code> otherwise.
  203. */
  204. public synchronized boolean isEmpty() {
  205. return count == 0;
  206. }
  207. /**
  208. * Returns an enumeration of the keys in this hashtable.
  209. *
  210. * @return an enumeration of the keys in this hashtable.
  211. * @see Enumeration
  212. * @see #elements()
  213. * @see #keySet()
  214. * @see Map
  215. */
  216. public synchronized Enumeration<K> keys() {
  217. return this.<K>getEnumeration(KEYS);
  218. }
  219. /**
  220. * Returns an enumeration of the values in this hashtable.
  221. * Use the Enumeration methods on the returned object to fetch the elements
  222. * sequentially.
  223. *
  224. * @return an enumeration of the values in this hashtable.
  225. * @see java.util.Enumeration
  226. * @see #keys()
  227. * @see #values()
  228. * @see Map
  229. */
  230. public synchronized Enumeration<V> elements() {
  231. return this.<V>getEnumeration(VALUES);
  232. }
  233. /**
  234. * Tests if some key maps into the specified value in this hashtable.
  235. * This operation is more expensive than the <code>containsKey</code>
  236. * method.<p>
  237. *
  238. * Note that this method is identical in functionality to containsValue,
  239. * (which is part of the Map interface in the collections framework).
  240. *
  241. * @param value a value to search for.
  242. * @return <code>true</code> if and only if some key maps to the
  243. * <code>value</code> argument in this hashtable as
  244. * determined by the <tt>equals</tt> method;
  245. * <code>false</code> otherwise.
  246. * @exception NullPointerException if the value is <code>null</code>.
  247. * @see #containsKey(Object)
  248. * @see #containsValue(Object)
  249. * @see Map
  250. */
  251. public synchronized boolean contains(Object value) {
  252. if (value == null) {
  253. throw new NullPointerException();
  254. }
  255. Entry tab[] = table;
  256. for (int i = tab.length ; i-- > 0 ;) {
  257. for (Entry<K,V> e = tab[i] ; e != null ; e = e.next) {
  258. if (e.value.equals(value)) {
  259. return true;
  260. }
  261. }
  262. }
  263. return false;
  264. }
  265. /**
  266. * Returns true if this Hashtable maps one or more keys to this value.<p>
  267. *
  268. * Note that this method is identical in functionality to contains
  269. * (which predates the Map interface).
  270. *
  271. * @param value value whose presence in this Hashtable is to be tested.
  272. * @return <tt>true</tt> if this map maps one or more keys to the
  273. * specified value.
  274. * @throws NullPointerException if the value is <code>null</code>.
  275. * @see Map
  276. * @since 1.2
  277. */
  278. public boolean containsValue(Object value) {
  279. return contains(value);
  280. }
  281. /**
  282. * Tests if the specified object is a key in this hashtable.
  283. *
  284. * @param key possible key.
  285. * @return <code>true</code> if and only if the specified object
  286. * is a key in this hashtable, as determined by the
  287. * <tt>equals</tt> method; <code>false</code> otherwise.
  288. * @throws NullPointerException if the key is <code>null</code>.
  289. * @see #contains(Object)
  290. */
  291. public synchronized boolean containsKey(Object key) {
  292. Entry tab[] = table;
  293. int hash = key.hashCode();
  294. int index = (hash & 0x7FFFFFFF) % tab.length;
  295. for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
  296. if ((e.hash == hash) && e.key.equals(key)) {
  297. return true;
  298. }
  299. }
  300. return false;
  301. }
  302. /**
  303. * Returns the value to which the specified key is mapped in this hashtable.
  304. *
  305. * @param key a key in the hashtable.
  306. * @return the value to which the key is mapped in this hashtable;
  307. * <code>null</code> if the key is not mapped to any value in
  308. * this hashtable.
  309. * @throws NullPointerException if the key is <code>null</code>.
  310. * @see #put(Object, Object)
  311. */
  312. public synchronized V get(Object key) {
  313. Entry tab[] = table;
  314. int hash = key.hashCode();
  315. int index = (hash & 0x7FFFFFFF) % tab.length;
  316. for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
  317. if ((e.hash == hash) && e.key.equals(key)) {
  318. return e.value;
  319. }
  320. }
  321. return null;
  322. }
  323. /**
  324. * Increases the capacity of and internally reorganizes this
  325. * hashtable, in order to accommodate and access its entries more
  326. * efficiently. This method is called automatically when the
  327. * number of keys in the hashtable exceeds this hashtable's capacity
  328. * and load factor.
  329. */
  330. protected void rehash() {
  331. int oldCapacity = table.length;
  332. Entry[] oldMap = table;
  333. int newCapacity = oldCapacity * 2 + 1;
  334. Entry[] newMap = new Entry[newCapacity];
  335. modCount++;
  336. threshold = (int)(newCapacity * loadFactor);
  337. table = newMap;
  338. for (int i = oldCapacity ; i-- > 0 ;) {
  339. for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
  340. Entry<K,V> e = old;
  341. old = old.next;
  342. int index = (e.hash & 0x7FFFFFFF) % newCapacity;
  343. e.next = newMap[index];
  344. newMap[index] = e;
  345. }
  346. }
  347. }
  348. /**
  349. * Maps the specified <code>key</code> to the specified
  350. * <code>value</code> in this hashtable. Neither the key nor the
  351. * value can be <code>null</code>. <p>
  352. *
  353. * The value can be retrieved by calling the <code>get</code> method
  354. * with a key that is equal to the original key.
  355. *
  356. * @param key the hashtable key.
  357. * @param value the value.
  358. * @return the previous value of the specified key in this hashtable,
  359. * or <code>null</code> if it did not have one.
  360. * @exception NullPointerException if the key or value is
  361. * <code>null</code>.
  362. * @see Object#equals(Object)
  363. * @see #get(Object)
  364. */
  365. public synchronized V put(K key, V value) {
  366. // Make sure the value is not null
  367. if (value == null) {
  368. throw new NullPointerException();
  369. }
  370. // Makes sure the key is not already in the hashtable.
  371. Entry tab[] = table;
  372. int hash = key.hashCode();
  373. int index = (hash & 0x7FFFFFFF) % tab.length;
  374. for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
  375. if ((e.hash == hash) && e.key.equals(key)) {
  376. V old = e.value;
  377. e.value = value;
  378. return old;
  379. }
  380. }
  381. modCount++;
  382. if (count >= threshold) {
  383. // Rehash the table if the threshold is exceeded
  384. rehash();
  385. tab = table;
  386. index = (hash & 0x7FFFFFFF) % tab.length;
  387. }
  388. // Creates the new entry.
  389. Entry<K,V> e = tab[index];
  390. tab[index] = new Entry<K,V>(hash, key, value, e);
  391. count++;
  392. return null;
  393. }
  394. /**
  395. * Removes the key (and its corresponding value) from this
  396. * hashtable. This method does nothing if the key is not in the hashtable.
  397. *
  398. * @param key the key that needs to be removed.
  399. * @return the value to which the key had been mapped in this hashtable,
  400. * or <code>null</code> if the key did not have a mapping.
  401. * @throws NullPointerException if the key is <code>null</code>.
  402. */
  403. public synchronized V remove(Object key) {
  404. Entry tab[] = table;
  405. int hash = key.hashCode();
  406. int index = (hash & 0x7FFFFFFF) % tab.length;
  407. for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) {
  408. if ((e.hash == hash) && e.key.equals(key)) {
  409. modCount++;
  410. if (prev != null) {
  411. prev.next = e.next;
  412. } else {
  413. tab[index] = e.next;
  414. }
  415. count--;
  416. V oldValue = e.value;
  417. e.value = null;
  418. return oldValue;
  419. }
  420. }
  421. return null;
  422. }
  423. /**
  424. * Copies all of the mappings from the specified Map to this Hashtable
  425. * These mappings will replace any mappings that this Hashtable had for any
  426. * of the keys currently in the specified Map.
  427. *
  428. * @param t Mappings to be stored in this map.
  429. * @throws NullPointerException if the specified map is null.
  430. * @since 1.2
  431. */
  432. public synchronized void putAll(Map<? extends K, ? extends V> t) {
  433. Iterator<? extends Map.Entry<? extends K, ? extends V>> i = t.entrySet().iterator();
  434. while (i.hasNext()) {
  435. Map.Entry<? extends K, ? extends V> e = i.next();
  436. put(e.getKey(), e.getValue());
  437. }
  438. }
  439. /**
  440. * Clears this hashtable so that it contains no keys.
  441. */
  442. public synchronized void clear() {
  443. Entry tab[] = table;
  444. modCount++;
  445. for (int index = tab.length; --index >= 0; )
  446. tab[index] = null;
  447. count = 0;
  448. }
  449. /**
  450. * Creates a shallow copy of this hashtable. All the structure of the
  451. * hashtable itself is copied, but the keys and values are not cloned.
  452. * This is a relatively expensive operation.
  453. *
  454. * @return a clone of the hashtable.
  455. */
  456. public synchronized Object clone() {
  457. try {
  458. Hashtable<K,V> t = (Hashtable<K,V>) super.clone();
  459. t.table = new Entry[table.length];
  460. for (int i = table.length ; i-- > 0 ; ) {
  461. t.table[i] = (table[i] != null)
  462. ? (Entry<K,V>) table[i].clone() : null;
  463. }
  464. t.keySet = null;
  465. t.entrySet = null;
  466. t.values = null;
  467. t.modCount = 0;
  468. return t;
  469. } catch (CloneNotSupportedException e) {
  470. // this shouldn't happen, since we are Cloneable
  471. throw new InternalError();
  472. }
  473. }
  474. /**
  475. * Returns a string representation of this <tt>Hashtable</tt> object
  476. * in the form of a set of entries, enclosed in braces and separated
  477. * by the ASCII characters "<tt>, </tt>" (comma and space). Each
  478. * entry is rendered as the key, an equals sign <tt>=</tt>, and the
  479. * associated element, where the <tt>toString</tt> method is used to
  480. * convert the key and element to strings. <p>Overrides to
  481. * <tt>toString</tt> method of <tt>Object</tt>.
  482. *
  483. * @return a string representation of this hashtable.
  484. */
  485. public synchronized String toString() {
  486. int max = size() - 1;
  487. StringBuffer buf = new StringBuffer();
  488. Iterator<Map.Entry<K,V>> it = entrySet().iterator();
  489. buf.append("{");
  490. for (int i = 0; i <= max; i++) {
  491. Map.Entry<K,V> e = it.next();
  492. K key = e.getKey();
  493. V value = e.getValue();
  494. buf.append((key == this ? "(this Map)" : (""+key)) + "=" +
  495. (value == this ? "(this Map)" : (""+value)));
  496. if (i < max)
  497. buf.append(", ");
  498. }
  499. buf.append("}");
  500. return buf.toString();
  501. }
  502. private <T> Enumeration<T> getEnumeration(int type) {
  503. if (count == 0) {
  504. return (Enumeration<T>)emptyEnumerator;
  505. } else {
  506. return new Enumerator<T>(type, false);
  507. }
  508. }
  509. private <T> Iterator<T> getIterator(int type) {
  510. if (count == 0) {
  511. return (Iterator<T>) emptyIterator;
  512. } else {
  513. return new Enumerator<T>(type, true);
  514. }
  515. }
  516. // Views
  517. /**
  518. * Each of these fields are initialized to contain an instance of the
  519. * appropriate view the first time this view is requested. The views are
  520. * stateless, so there's no reason to create more than one of each.
  521. */
  522. private transient volatile Set<K> keySet = null;
  523. private transient volatile Set<Map.Entry<K,V>> entrySet = null;
  524. private transient volatile Collection<V> values = null;
  525. /**
  526. * Returns a Set view of the keys contained in this Hashtable. The Set
  527. * is backed by the Hashtable, so changes to the Hashtable are reflected
  528. * in the Set, and vice-versa. The Set supports element removal
  529. * (which removes the corresponding entry from the Hashtable), but not
  530. * element addition.
  531. *
  532. * @return a set view of the keys contained in this map.
  533. * @since 1.2
  534. */
  535. public Set<K> keySet() {
  536. if (keySet == null)
  537. keySet = Collections.synchronizedSet(new KeySet(), this);
  538. return keySet;
  539. }
  540. private class KeySet extends AbstractSet<K> {
  541. public Iterator<K> iterator() {
  542. return getIterator(KEYS);
  543. }
  544. public int size() {
  545. return count;
  546. }
  547. public boolean contains(Object o) {
  548. return containsKey(o);
  549. }
  550. public boolean remove(Object o) {
  551. return Hashtable.this.remove(o) != null;
  552. }
  553. public void clear() {
  554. Hashtable.this.clear();
  555. }
  556. }
  557. /**
  558. * Returns a Set view of the entries contained in this Hashtable.
  559. * Each element in this collection is a Map.Entry. The Set is
  560. * backed by the Hashtable, so changes to the Hashtable are reflected in
  561. * the Set, and vice-versa. The Set supports element removal
  562. * (which removes the corresponding entry from the Hashtable),
  563. * but not element addition.
  564. *
  565. * @return a set view of the mappings contained in this map.
  566. * @see Map.Entry
  567. * @since 1.2
  568. */
  569. public Set<Map.Entry<K,V>> entrySet() {
  570. if (entrySet==null)
  571. entrySet = Collections.synchronizedSet(new EntrySet(), this);
  572. return entrySet;
  573. }
  574. private class EntrySet extends AbstractSet/*<Map.Entry<K,V>>*/ {
  575. public Iterator/*<Map.Entry<K,V>>*/ iterator() {
  576. return getIterator(ENTRIES);
  577. }
  578. public boolean add(Object/*Map.Entry<K,V>*/ o) {
  579. return super.add(o);
  580. }
  581. public boolean contains(Object o) {
  582. if (!(o instanceof Map.Entry))
  583. return false;
  584. Map.Entry entry = (Map.Entry)o;
  585. Object key = entry.getKey();
  586. Entry[] tab = table;
  587. int hash = key.hashCode();
  588. int index = (hash & 0x7FFFFFFF) % tab.length;
  589. for (Entry e = tab[index]; e != null; e = e.next)
  590. if (e.hash==hash && e.equals(entry))
  591. return true;
  592. return false;
  593. }
  594. public boolean remove(Object o) {
  595. if (!(o instanceof Map.Entry))
  596. return false;
  597. Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
  598. K key = entry.getKey();
  599. Entry[] tab = table;
  600. int hash = key.hashCode();
  601. int index = (hash & 0x7FFFFFFF) % tab.length;
  602. for (Entry<K,V> e = tab[index], prev = null; e != null;
  603. prev = e, e = e.next) {
  604. if (e.hash==hash && e.equals(entry)) {
  605. modCount++;
  606. if (prev != null)
  607. prev.next = e.next;
  608. else
  609. tab[index] = e.next;
  610. count--;
  611. e.value = null;
  612. return true;
  613. }
  614. }
  615. return false;
  616. }
  617. public int size() {
  618. return count;
  619. }
  620. public void clear() {
  621. Hashtable.this.clear();
  622. }
  623. }
  624. /**
  625. * Returns a Collection view of the values contained in this Hashtable.
  626. * The Collection is backed by the Hashtable, so changes to the Hashtable
  627. * are reflected in the Collection, and vice-versa. The Collection
  628. * supports element removal (which removes the corresponding entry from
  629. * the Hashtable), but not element addition.
  630. *
  631. * @return a collection view of the values contained in this map.
  632. * @since 1.2
  633. */
  634. public Collection<V> values() {
  635. if (values==null)
  636. values = Collections.synchronizedCollection(new ValueCollection(),
  637. this);
  638. return values;
  639. }
  640. private class ValueCollection extends AbstractCollection<V> {
  641. public Iterator<V> iterator() {
  642. return getIterator(VALUES);
  643. }
  644. public int size() {
  645. return count;
  646. }
  647. public boolean contains(Object o) {
  648. return containsValue(o);
  649. }
  650. public void clear() {
  651. Hashtable.this.clear();
  652. }
  653. }
  654. // Comparison and hashing
  655. /**
  656. * Compares the specified Object with this Map for equality,
  657. * as per the definition in the Map interface.
  658. *
  659. * @param o object to be compared for equality with this Hashtable
  660. * @return true if the specified Object is equal to this Map.
  661. * @see Map#equals(Object)
  662. * @since 1.2
  663. */
  664. public synchronized boolean equals(Object o) {
  665. if (o == this)
  666. return true;
  667. if (!(o instanceof Map))
  668. return false;
  669. Map<K,V> t = (Map<K,V>) o;
  670. if (t.size() != size())
  671. return false;
  672. try {
  673. Iterator<Map.Entry<K,V>> i = entrySet().iterator();
  674. while (i.hasNext()) {
  675. Map.Entry<K,V> e = i.next();
  676. K key = e.getKey();
  677. V value = e.getValue();
  678. if (value == null) {
  679. if (!(t.get(key)==null && t.containsKey(key)))
  680. return false;
  681. } else {
  682. if (!value.equals(t.get(key)))
  683. return false;
  684. }
  685. }
  686. } catch(ClassCastException unused) {
  687. return false;
  688. } catch(NullPointerException unused) {
  689. return false;
  690. }
  691. return true;
  692. }
  693. /**
  694. * Returns the hash code value for this Map as per the definition in the
  695. * Map interface.
  696. *
  697. * @see Map#hashCode()
  698. * @since 1.2
  699. */
  700. public synchronized int hashCode() {
  701. /*
  702. * This code detects the recursion caused by computing the hash code
  703. * of a self-referential hash table and prevents the stack overflow
  704. * that would otherwise result. This allows certain 1.1-era
  705. * applets with self-referential hash tables to work. This code
  706. * abuses the loadFactor field to do double-duty as a hashCode
  707. * in progress flag, so as not to worsen the space performance.
  708. * A negative load factor indicates that hash code computation is
  709. * in progress.
  710. */
  711. int h = 0;
  712. if (count == 0 || loadFactor < 0)
  713. return h; // Returns zero
  714. loadFactor = -loadFactor; // Mark hashCode computation in progress
  715. Entry[] tab = table;
  716. for (int i = 0; i < tab.length; i++)
  717. for (Entry e = tab[i]; e != null; e = e.next)
  718. h += e.key.hashCode() ^ e.value.hashCode();
  719. loadFactor = -loadFactor; // Mark hashCode computation complete
  720. return h;
  721. }
  722. /**
  723. * Save the state of the Hashtable to a stream (i.e., serialize it).
  724. *
  725. * @serialData The <i>capacity</i> of the Hashtable (the length of the
  726. * bucket array) is emitted (int), followed by the
  727. * <i>size</i> of the Hashtable (the number of key-value
  728. * mappings), followed by the key (Object) and value (Object)
  729. * for each key-value mapping represented by the Hashtable
  730. * The key-value mappings are emitted in no particular order.
  731. */
  732. private synchronized void writeObject(java.io.ObjectOutputStream s)
  733. throws IOException
  734. {
  735. // Write out the length, threshold, loadfactor
  736. s.defaultWriteObject();
  737. // Write out length, count of elements and then the key/value objects
  738. s.writeInt(table.length);
  739. s.writeInt(count);
  740. for (int index = table.length-1; index >= 0; index--) {
  741. Entry entry = table[index];
  742. while (entry != null) {
  743. s.writeObject(entry.key);
  744. s.writeObject(entry.value);
  745. entry = entry.next;
  746. }
  747. }
  748. }
  749. /**
  750. * Reconstitute the Hashtable from a stream (i.e., deserialize it).
  751. */
  752. private void readObject(java.io.ObjectInputStream s)
  753. throws IOException, ClassNotFoundException
  754. {
  755. // Read in the length, threshold, and loadfactor
  756. s.defaultReadObject();
  757. // Read the original length of the array and number of elements
  758. int origlength = s.readInt();
  759. int elements = s.readInt();
  760. // Compute new size with a bit of room 5% to grow but
  761. // no larger than the original size. Make the length
  762. // odd if it's large enough, this helps distribute the entries.
  763. // Guard against the length ending up zero, that's not valid.
  764. int length = (int)(elements * loadFactor) + (elements / 20) + 3;
  765. if (length > elements && (length & 1) == 0)
  766. length--;
  767. if (origlength > 0 && length > origlength)
  768. length = origlength;
  769. table = new Entry[length];
  770. count = 0;
  771. // Read the number of elements and then all the key/value objects
  772. for (; elements > 0; elements--) {
  773. K key = (K)s.readObject();
  774. V value = (V)s.readObject();
  775. // synch could be eliminated for performance
  776. reconstitutionPut(key, value);
  777. }
  778. }
  779. /**
  780. * The put method used by readObject. This is provided because put
  781. * is overridable and should not be called in readObject since the
  782. * subclass will not yet be initialized.
  783. *
  784. * <p>This differs from the regular put method in several ways. No
  785. * checking for rehashing is necessary since the number of elements
  786. * initially in the table is known. The modCount is not incremented
  787. * because we are creating a new instance. Also, no return value
  788. * is needed.
  789. */
  790. private void reconstitutionPut(K key, V value)
  791. throws StreamCorruptedException
  792. {
  793. if (value == null) {
  794. throw new java.io.StreamCorruptedException();
  795. }
  796. // Makes sure the key is not already in the hashtable.
  797. // This should not happen in deserialized version.
  798. Entry[] tab = table;
  799. int hash = key.hashCode();
  800. int index = (hash & 0x7FFFFFFF) % tab.length;
  801. for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
  802. if ((e.hash == hash) && e.key.equals(key)) {
  803. throw new java.io.StreamCorruptedException();
  804. }
  805. }
  806. // Creates the new entry.
  807. Entry<K,V> e = tab[index];
  808. tab[index] = new Entry<K,V>(hash, key, value, e);
  809. count++;
  810. }
  811. /**
  812. * Hashtable collision list.
  813. */
  814. private static class Entry<K,V> implements Map.Entry<K,V> {
  815. int hash;
  816. K key;
  817. V value;
  818. Entry<K,V> next;
  819. protected Entry(int hash, K key, V value, Entry<K,V> next) {
  820. this.hash = hash;
  821. this.key = key;
  822. this.value = value;
  823. this.next = next;
  824. }
  825. protected Object clone() {
  826. return new Entry<K,V>(hash, key, value,
  827. (next==null ? null : (Entry<K,V>) next.clone()));
  828. }
  829. // Map.Entry Ops
  830. public K getKey() {
  831. return key;
  832. }
  833. public V getValue() {
  834. return value;
  835. }
  836. public V setValue(V value) {
  837. if (value == null)
  838. throw new NullPointerException();
  839. V oldValue = this.value;
  840. this.value = value;
  841. return oldValue;
  842. }
  843. public boolean equals(Object o) {
  844. if (!(o instanceof Map.Entry))
  845. return false;
  846. Map.Entry e = (Map.Entry)o;
  847. return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
  848. (value==null ? e.getValue()==null : value.equals(e.getValue()));
  849. }
  850. public int hashCode() {
  851. return hash ^ (value==null ? 0 : value.hashCode());
  852. }
  853. public String toString() {
  854. return key.toString()+"="+value.toString();
  855. }
  856. }
  857. // Types of Enumerations/Iterations
  858. private static final int KEYS = 0;
  859. private static final int VALUES = 1;
  860. private static final int ENTRIES = 2;
  861. /**
  862. * A hashtable enumerator class. This class implements both the
  863. * Enumeration and Iterator interfaces, but individual instances
  864. * can be created with the Iterator methods disabled. This is necessary
  865. * to avoid unintentionally increasing the capabilities granted a user
  866. * by passing an Enumeration.
  867. */
  868. private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
  869. Entry[] table = Hashtable.this.table;
  870. int index = table.length;
  871. Entry<K,V> entry = null;
  872. Entry<K,V> lastReturned = null;
  873. int type;
  874. /**
  875. * Indicates whether this Enumerator is serving as an Iterator
  876. * or an Enumeration. (true -> Iterator).
  877. */
  878. boolean iterator;
  879. /**
  880. * The modCount value that the iterator believes that the backing
  881. * List should have. If this expectation is violated, the iterator
  882. * has detected concurrent modification.
  883. */
  884. protected int expectedModCount = modCount;
  885. Enumerator(int type, boolean iterator) {
  886. this.type = type;
  887. this.iterator = iterator;
  888. }
  889. public boolean hasMoreElements() {
  890. Entry<K,V> e = entry;
  891. int i = index;
  892. Entry[] t = table;
  893. /* Use locals for faster loop iteration */
  894. while (e == null && i > 0) {
  895. e = t[--i];
  896. }
  897. entry = e;
  898. index = i;
  899. return e != null;
  900. }
  901. public T nextElement() {
  902. Entry<K,V> et = entry;
  903. int i = index;
  904. Entry[] t = table;
  905. /* Use locals for faster loop iteration */
  906. while (et == null && i > 0) {
  907. et = t[--i];
  908. }
  909. entry = et;
  910. index = i;
  911. if (et != null) {
  912. Entry<K,V> e = lastReturned = entry;
  913. entry = e.next;
  914. return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
  915. }
  916. throw new NoSuchElementException("Hashtable Enumerator");
  917. }
  918. // Iterator methods
  919. public boolean hasNext() {
  920. return hasMoreElements();
  921. }
  922. public T next() {
  923. if (modCount != expectedModCount)
  924. throw new ConcurrentModificationException();
  925. return nextElement();
  926. }
  927. public void remove() {
  928. if (!iterator)
  929. throw new UnsupportedOperationException();
  930. if (lastReturned == null)
  931. throw new IllegalStateException("Hashtable Enumerator");
  932. if (modCount != expectedModCount)
  933. throw new ConcurrentModificationException();
  934. synchronized(Hashtable.this) {
  935. Entry[] tab = Hashtable.this.table;
  936. int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;
  937. for (Entry<K,V> e = tab[index], prev = null; e != null;
  938. prev = e, e = e.next) {
  939. if (e == lastReturned) {
  940. modCount++;
  941. expectedModCount++;
  942. if (prev == null)
  943. tab[index] = e.next;
  944. else
  945. prev.next = e.next;
  946. count--;
  947. lastReturned = null;
  948. return;
  949. }
  950. }
  951. throw new ConcurrentModificationException();
  952. }
  953. }
  954. }
  955. private static Enumeration emptyEnumerator = new EmptyEnumerator();
  956. private static Iterator emptyIterator = new EmptyIterator();
  957. /**
  958. * A hashtable enumerator class for empty hash tables, specializes
  959. * the general Enumerator
  960. */
  961. private static class EmptyEnumerator implements Enumeration<Object> {
  962. EmptyEnumerator() {
  963. }
  964. public boolean hasMoreElements() {
  965. return false;
  966. }
  967. public Object nextElement() {
  968. throw new NoSuchElementException("Hashtable Enumerator");
  969. }
  970. }
  971. /**
  972. * A hashtable iterator class for empty hash tables
  973. */
  974. private static class EmptyIterator implements Iterator<Object> {
  975. EmptyIterator() {
  976. }
  977. public boolean hasNext() {
  978. return false;
  979. }
  980. public Object next() {
  981. throw new NoSuchElementException("Hashtable Iterator");
  982. }
  983. public void remove() {
  984. throw new IllegalStateException("Hashtable Iterator");
  985. }
  986. }
  987. }