HashMap.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. /* HashMap.java -- a class providing a basic hashtable data structure,
  2. mapping Object --> Object
  3. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
  4. This file is part of GNU Classpath.
  5. GNU Classpath is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. GNU Classpath is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Classpath; see the file COPYING. If not, write to the
  15. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. 02110-1301 USA.
  17. Linking this library statically or dynamically with other modules is
  18. making a combined work based on this library. Thus, the terms and
  19. conditions of the GNU General Public License cover the whole
  20. combination.
  21. As a special exception, the copyright holders of this library give you
  22. permission to link this library with independent modules to produce an
  23. executable, regardless of the license terms of these independent
  24. modules, and to copy and distribute the resulting executable under
  25. terms of your choice, provided that you also meet, for each linked
  26. independent module, the terms and conditions of the license of that
  27. module. An independent module is a module which is not derived from
  28. or based on this library. If you modify this library, you may extend
  29. this exception to your version of the library, but you are not
  30. obligated to do so. If you do not wish to do so, delete this
  31. exception statement from your version. */
  32. package java.util;
  33. import java.io.IOException;
  34. import java.io.ObjectInputStream;
  35. import java.io.ObjectOutputStream;
  36. import java.io.Serializable;
  37. // NOTE: This implementation is very similar to that of Hashtable. If you fix
  38. // a bug in here, chances are you should make a similar change to the Hashtable
  39. // code.
  40. // NOTE: This implementation has some nasty coding style in order to
  41. // support LinkedHashMap, which extends this.
  42. /**
  43. * This class provides a hashtable-backed implementation of the
  44. * Map interface.
  45. * <p>
  46. *
  47. * It uses a hash-bucket approach; that is, hash collisions are handled
  48. * by linking the new node off of the pre-existing node (or list of
  49. * nodes). In this manner, techniques such as linear probing (which
  50. * can cause primary clustering) and rehashing (which does not fit very
  51. * well with Java's method of precomputing hash codes) are avoided.
  52. * <p>
  53. *
  54. * Under ideal circumstances (no collisions), HashMap offers O(1)
  55. * performance on most operations (<code>containsValue()</code> is,
  56. * of course, O(n)). In the worst case (all keys map to the same
  57. * hash code -- very unlikely), most operations are O(n).
  58. * <p>
  59. *
  60. * HashMap is part of the JDK1.2 Collections API. It differs from
  61. * Hashtable in that it accepts the null key and null values, and it
  62. * does not support "Enumeration views." Also, it is not synchronized;
  63. * if you plan to use it in multiple threads, consider using:<br>
  64. * <code>Map m = Collections.synchronizedMap(new HashMap(...));</code>
  65. * <p>
  66. *
  67. * The iterators are <i>fail-fast</i>, meaning that any structural
  68. * modification, except for <code>remove()</code> called on the iterator
  69. * itself, cause the iterator to throw a
  70. * <code>ConcurrentModificationException</code> rather than exhibit
  71. * non-deterministic behavior.
  72. *
  73. * @author Jon Zeppieri
  74. * @author Jochen Hoenicke
  75. * @author Bryce McKinlay
  76. * @author Eric Blake (ebb9@email.byu.edu)
  77. * @see Object#hashCode()
  78. * @see Collection
  79. * @see Map
  80. * @see TreeMap
  81. * @see LinkedHashMap
  82. * @see IdentityHashMap
  83. * @see Hashtable
  84. * @since 1.2
  85. * @status updated to 1.4
  86. */
  87. public class HashMap<K, V> extends AbstractMap<K, V>
  88. implements Map<K, V>, Cloneable, Serializable
  89. {
  90. /**
  91. * Default number of buckets; this is currently set to 16.
  92. * Package visible for use by HashSet.
  93. */
  94. static final int DEFAULT_CAPACITY = 16;
  95. /**
  96. * The default load factor; this is explicitly specified by the spec.
  97. * Package visible for use by HashSet.
  98. */
  99. static final float DEFAULT_LOAD_FACTOR = 0.75f;
  100. /**
  101. * Compatible with JDK 1.2.
  102. */
  103. private static final long serialVersionUID = 362498820763181265L;
  104. /**
  105. * The rounded product of the capacity and the load factor; when the number
  106. * of elements exceeds the threshold, the HashMap calls
  107. * <code>rehash()</code>.
  108. * @serial the threshold for rehashing
  109. */
  110. private int threshold;
  111. /**
  112. * Load factor of this HashMap: used in computing the threshold.
  113. * Package visible for use by HashSet.
  114. * @serial the load factor
  115. */
  116. final float loadFactor;
  117. /**
  118. * Array containing the actual key-value mappings.
  119. * Package visible for use by nested and subclasses.
  120. */
  121. transient HashEntry<K, V>[] buckets;
  122. /**
  123. * Counts the number of modifications this HashMap has undergone, used
  124. * by Iterators to know when to throw ConcurrentModificationExceptions.
  125. * Package visible for use by nested and subclasses.
  126. */
  127. transient int modCount;
  128. /**
  129. * The size of this HashMap: denotes the number of key-value pairs.
  130. * Package visible for use by nested and subclasses.
  131. */
  132. transient int size;
  133. /**
  134. * The cache for {@link #entrySet()}.
  135. */
  136. private transient Set<Map.Entry<K, V>> entries;
  137. /**
  138. * Class to represent an entry in the hash table. Holds a single key-value
  139. * pair. Package visible for use by subclass.
  140. *
  141. * @author Eric Blake (ebb9@email.byu.edu)
  142. */
  143. static class HashEntry<K, V> extends AbstractMap.SimpleEntry<K, V>
  144. {
  145. /**
  146. * The next entry in the linked list. Package visible for use by subclass.
  147. */
  148. HashEntry<K, V> next;
  149. /**
  150. * Simple constructor.
  151. * @param key the key
  152. * @param value the value
  153. */
  154. HashEntry(K key, V value)
  155. {
  156. super(key, value);
  157. }
  158. /**
  159. * Called when this entry is accessed via {@link #put(Object, Object)}.
  160. * This version does nothing, but in LinkedHashMap, it must do some
  161. * bookkeeping for access-traversal mode.
  162. */
  163. void access()
  164. {
  165. }
  166. /**
  167. * Called when this entry is removed from the map. This version simply
  168. * returns the value, but in LinkedHashMap, it must also do bookkeeping.
  169. *
  170. * @return the value of this key as it is removed
  171. */
  172. V cleanup()
  173. {
  174. return value;
  175. }
  176. }
  177. /**
  178. * Construct a new HashMap with the default capacity (11) and the default
  179. * load factor (0.75).
  180. */
  181. public HashMap()
  182. {
  183. this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR);
  184. }
  185. /**
  186. * Construct a new HashMap from the given Map, with initial capacity
  187. * the greater of the size of <code>m</code> or the default of 11.
  188. * <p>
  189. *
  190. * Every element in Map m will be put into this new HashMap.
  191. *
  192. * @param m a Map whose key / value pairs will be put into the new HashMap.
  193. * <b>NOTE: key / value pairs are not cloned in this constructor.</b>
  194. * @throws NullPointerException if m is null
  195. */
  196. public HashMap(Map<? extends K, ? extends V> m)
  197. {
  198. this(Math.max(m.size() * 2, DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
  199. putAll(m);
  200. }
  201. /**
  202. * Construct a new HashMap with a specific inital capacity and
  203. * default load factor of 0.75.
  204. *
  205. * @param initialCapacity the initial capacity of this HashMap (&gt;=0)
  206. * @throws IllegalArgumentException if (initialCapacity &lt; 0)
  207. */
  208. public HashMap(int initialCapacity)
  209. {
  210. this(initialCapacity, DEFAULT_LOAD_FACTOR);
  211. }
  212. /**
  213. * Construct a new HashMap with a specific inital capacity and load factor.
  214. *
  215. * @param initialCapacity the initial capacity (&gt;=0)
  216. * @param loadFactor the load factor (&gt; 0, not NaN)
  217. * @throws IllegalArgumentException if (initialCapacity &lt; 0) ||
  218. * ! (loadFactor &gt; 0.0)
  219. */
  220. public HashMap(int initialCapacity, float loadFactor)
  221. {
  222. if (initialCapacity < 0)
  223. throw new IllegalArgumentException("Illegal Capacity: "
  224. + initialCapacity);
  225. if (! (loadFactor > 0)) // check for NaN too
  226. throw new IllegalArgumentException("Illegal Load: " + loadFactor);
  227. if (initialCapacity == 0)
  228. initialCapacity = 1;
  229. buckets = (HashEntry<K, V>[]) new HashEntry[initialCapacity];
  230. this.loadFactor = loadFactor;
  231. threshold = (int) (initialCapacity * loadFactor);
  232. }
  233. /**
  234. * Returns the number of kay-value mappings currently in this Map.
  235. *
  236. * @return the size
  237. */
  238. public int size()
  239. {
  240. return size;
  241. }
  242. /**
  243. * Returns true if there are no key-value mappings currently in this Map.
  244. *
  245. * @return <code>size() == 0</code>
  246. */
  247. public boolean isEmpty()
  248. {
  249. return size == 0;
  250. }
  251. /**
  252. * Return the value in this HashMap associated with the supplied key,
  253. * or <code>null</code> if the key maps to nothing. NOTE: Since the value
  254. * could also be null, you must use containsKey to see if this key
  255. * actually maps to something.
  256. *
  257. * @param key the key for which to fetch an associated value
  258. * @return what the key maps to, if present
  259. * @see #put(Object, Object)
  260. * @see #containsKey(Object)
  261. */
  262. public V get(Object key)
  263. {
  264. int idx = hash(key);
  265. HashEntry<K, V> e = buckets[idx];
  266. while (e != null)
  267. {
  268. if (equals(key, e.key))
  269. return e.value;
  270. e = e.next;
  271. }
  272. return null;
  273. }
  274. /**
  275. * Returns true if the supplied object <code>equals()</code> a key
  276. * in this HashMap.
  277. *
  278. * @param key the key to search for in this HashMap
  279. * @return true if the key is in the table
  280. * @see #containsValue(Object)
  281. */
  282. public boolean containsKey(Object key)
  283. {
  284. int idx = hash(key);
  285. HashEntry<K, V> e = buckets[idx];
  286. while (e != null)
  287. {
  288. if (equals(key, e.key))
  289. return true;
  290. e = e.next;
  291. }
  292. return false;
  293. }
  294. /**
  295. * Puts the supplied value into the Map, mapped by the supplied key.
  296. * The value may be retrieved by any object which <code>equals()</code>
  297. * this key. NOTE: Since the prior value could also be null, you must
  298. * first use containsKey if you want to see if you are replacing the
  299. * key's mapping.
  300. *
  301. * @param key the key used to locate the value
  302. * @param value the value to be stored in the HashMap
  303. * @return the prior mapping of the key, or null if there was none
  304. * @see #get(Object)
  305. * @see Object#equals(Object)
  306. */
  307. public V put(K key, V value)
  308. {
  309. int idx = hash(key);
  310. HashEntry<K, V> e = buckets[idx];
  311. int hash1 = key == null ? 0 : key.hashCode();
  312. while (e != null)
  313. {
  314. int hash2 = e.key == null ? 0 : e.key.hashCode();
  315. if ((hash1 == hash2) && equals(key, e.key))
  316. {
  317. e.access(); // Must call this for bookkeeping in LinkedHashMap.
  318. V r = e.value;
  319. e.value = value;
  320. return r;
  321. }
  322. else
  323. e = e.next;
  324. }
  325. // At this point, we know we need to add a new entry.
  326. modCount++;
  327. if (++size > threshold)
  328. {
  329. rehash();
  330. // Need a new hash value to suit the bigger table.
  331. idx = hash(key);
  332. }
  333. // LinkedHashMap cannot override put(), hence this call.
  334. addEntry(key, value, idx, true);
  335. return null;
  336. }
  337. /**
  338. * Copies all elements of the given map into this hashtable. If this table
  339. * already has a mapping for a key, the new mapping replaces the current
  340. * one.
  341. *
  342. * @param m the map to be hashed into this
  343. */
  344. public void putAll(Map<? extends K, ? extends V> m)
  345. {
  346. final Map<K,V> addMap = (Map<K,V>) m;
  347. final Iterator<Map.Entry<K,V>> it = addMap.entrySet().iterator();
  348. while (it.hasNext())
  349. {
  350. final Map.Entry<K,V> e = it.next();
  351. // Optimize in case the Entry is one of our own.
  352. if (e instanceof AbstractMap.SimpleEntry)
  353. {
  354. AbstractMap.SimpleEntry<? extends K, ? extends V> entry
  355. = (AbstractMap.SimpleEntry<? extends K, ? extends V>) e;
  356. put(entry.key, entry.value);
  357. }
  358. else
  359. put(e.getKey(), e.getValue());
  360. }
  361. }
  362. /**
  363. * Removes from the HashMap and returns the value which is mapped by the
  364. * supplied key. If the key maps to nothing, then the HashMap remains
  365. * unchanged, and <code>null</code> is returned. NOTE: Since the value
  366. * could also be null, you must use containsKey to see if you are
  367. * actually removing a mapping.
  368. *
  369. * @param key the key used to locate the value to remove
  370. * @return whatever the key mapped to, if present
  371. */
  372. public V remove(Object key)
  373. {
  374. int idx = hash(key);
  375. HashEntry<K, V> e = buckets[idx];
  376. HashEntry<K, V> last = null;
  377. while (e != null)
  378. {
  379. if (equals(key, e.key))
  380. {
  381. modCount++;
  382. if (last == null)
  383. buckets[idx] = e.next;
  384. else
  385. last.next = e.next;
  386. size--;
  387. // Method call necessary for LinkedHashMap to work correctly.
  388. return e.cleanup();
  389. }
  390. last = e;
  391. e = e.next;
  392. }
  393. return null;
  394. }
  395. /**
  396. * Clears the Map so it has no keys. This is O(1).
  397. */
  398. public void clear()
  399. {
  400. if (size != 0)
  401. {
  402. modCount++;
  403. Arrays.fill(buckets, null);
  404. size = 0;
  405. }
  406. }
  407. /**
  408. * Returns true if this HashMap contains a value <code>o</code>, such that
  409. * <code>o.equals(value)</code>.
  410. *
  411. * @param value the value to search for in this HashMap
  412. * @return true if at least one key maps to the value
  413. * @see #containsKey(Object)
  414. */
  415. public boolean containsValue(Object value)
  416. {
  417. for (int i = buckets.length - 1; i >= 0; i--)
  418. {
  419. HashEntry<K, V> e = buckets[i];
  420. while (e != null)
  421. {
  422. if (equals(value, e.value))
  423. return true;
  424. e = e.next;
  425. }
  426. }
  427. return false;
  428. }
  429. /**
  430. * Returns a shallow clone of this HashMap. The Map itself is cloned,
  431. * but its contents are not. This is O(n).
  432. *
  433. * @return the clone
  434. */
  435. public Object clone()
  436. {
  437. HashMap<K, V> copy = null;
  438. try
  439. {
  440. copy = (HashMap<K, V>) super.clone();
  441. }
  442. catch (CloneNotSupportedException x)
  443. {
  444. // This is impossible.
  445. }
  446. copy.buckets = (HashEntry<K, V>[]) new HashEntry[buckets.length];
  447. copy.putAllInternal(this);
  448. // Clear the entry cache. AbstractMap.clone() does the others.
  449. copy.entries = null;
  450. return copy;
  451. }
  452. /**
  453. * Returns a "set view" of this HashMap's keys. The set is backed by the
  454. * HashMap, so changes in one show up in the other. The set supports
  455. * element removal, but not element addition.
  456. *
  457. * @return a set view of the keys
  458. * @see #values()
  459. * @see #entrySet()
  460. */
  461. public Set<K> keySet()
  462. {
  463. if (keys == null)
  464. // Create an AbstractSet with custom implementations of those methods
  465. // that can be overridden easily and efficiently.
  466. keys = new AbstractSet<K>()
  467. {
  468. public int size()
  469. {
  470. return size;
  471. }
  472. public Iterator<K> iterator()
  473. {
  474. // Cannot create the iterator directly, because of LinkedHashMap.
  475. return HashMap.this.iterator(KEYS);
  476. }
  477. public void clear()
  478. {
  479. HashMap.this.clear();
  480. }
  481. public boolean contains(Object o)
  482. {
  483. return containsKey(o);
  484. }
  485. public boolean remove(Object o)
  486. {
  487. // Test against the size of the HashMap to determine if anything
  488. // really got removed. This is necessary because the return value
  489. // of HashMap.remove() is ambiguous in the null case.
  490. int oldsize = size;
  491. HashMap.this.remove(o);
  492. return oldsize != size;
  493. }
  494. };
  495. return keys;
  496. }
  497. /**
  498. * Returns a "collection view" (or "bag view") of this HashMap's values.
  499. * The collection is backed by the HashMap, so changes in one show up
  500. * in the other. The collection supports element removal, but not element
  501. * addition.
  502. *
  503. * @return a bag view of the values
  504. * @see #keySet()
  505. * @see #entrySet()
  506. */
  507. public Collection<V> values()
  508. {
  509. if (values == null)
  510. // We don't bother overriding many of the optional methods, as doing so
  511. // wouldn't provide any significant performance advantage.
  512. values = new AbstractCollection<V>()
  513. {
  514. public int size()
  515. {
  516. return size;
  517. }
  518. public Iterator<V> iterator()
  519. {
  520. // Cannot create the iterator directly, because of LinkedHashMap.
  521. return HashMap.this.iterator(VALUES);
  522. }
  523. public void clear()
  524. {
  525. HashMap.this.clear();
  526. }
  527. };
  528. return values;
  529. }
  530. /**
  531. * Returns a "set view" of this HashMap's entries. The set is backed by
  532. * the HashMap, so changes in one show up in the other. The set supports
  533. * element removal, but not element addition.<p>
  534. *
  535. * Note that the iterators for all three views, from keySet(), entrySet(),
  536. * and values(), traverse the HashMap in the same sequence.
  537. *
  538. * @return a set view of the entries
  539. * @see #keySet()
  540. * @see #values()
  541. * @see Map.Entry
  542. */
  543. public Set<Map.Entry<K, V>> entrySet()
  544. {
  545. if (entries == null)
  546. // Create an AbstractSet with custom implementations of those methods
  547. // that can be overridden easily and efficiently.
  548. entries = new AbstractSet<Map.Entry<K, V>>()
  549. {
  550. public int size()
  551. {
  552. return size;
  553. }
  554. public Iterator<Map.Entry<K, V>> iterator()
  555. {
  556. // Cannot create the iterator directly, because of LinkedHashMap.
  557. return HashMap.this.iterator(ENTRIES);
  558. }
  559. public void clear()
  560. {
  561. HashMap.this.clear();
  562. }
  563. public boolean contains(Object o)
  564. {
  565. return getEntry(o) != null;
  566. }
  567. public boolean remove(Object o)
  568. {
  569. HashEntry<K, V> e = getEntry(o);
  570. if (e != null)
  571. {
  572. HashMap.this.remove(e.key);
  573. return true;
  574. }
  575. return false;
  576. }
  577. };
  578. return entries;
  579. }
  580. /**
  581. * Helper method for put, that creates and adds a new Entry. This is
  582. * overridden in LinkedHashMap for bookkeeping purposes.
  583. *
  584. * @param key the key of the new Entry
  585. * @param value the value
  586. * @param idx the index in buckets where the new Entry belongs
  587. * @param callRemove whether to call the removeEldestEntry method
  588. * @see #put(Object, Object)
  589. */
  590. void addEntry(K key, V value, int idx, boolean callRemove)
  591. {
  592. HashEntry<K, V> e = new HashEntry<K, V>(key, value);
  593. e.next = buckets[idx];
  594. buckets[idx] = e;
  595. }
  596. /**
  597. * Helper method for entrySet(), which matches both key and value
  598. * simultaneously.
  599. *
  600. * @param o the entry to match
  601. * @return the matching entry, if found, or null
  602. * @see #entrySet()
  603. */
  604. // Package visible, for use in nested classes.
  605. final HashEntry<K, V> getEntry(Object o)
  606. {
  607. if (! (o instanceof Map.Entry))
  608. return null;
  609. Map.Entry<K, V> me = (Map.Entry<K, V>) o;
  610. K key = me.getKey();
  611. int idx = hash(key);
  612. HashEntry<K, V> e = buckets[idx];
  613. while (e != null)
  614. {
  615. if (equals(e.key, key))
  616. return equals(e.value, me.getValue()) ? e : null;
  617. e = e.next;
  618. }
  619. return null;
  620. }
  621. /**
  622. * Helper method that returns an index in the buckets array for `key'
  623. * based on its hashCode(). Package visible for use by subclasses.
  624. *
  625. * @param key the key
  626. * @return the bucket number
  627. */
  628. final int hash(Object key)
  629. {
  630. return key == null ? 0 : Math.abs(key.hashCode() % buckets.length);
  631. }
  632. /**
  633. * Generates a parameterized iterator. Must be overrideable, since
  634. * LinkedHashMap iterates in a different order.
  635. *
  636. * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
  637. * @return the appropriate iterator
  638. */
  639. <T> Iterator<T> iterator(int type)
  640. {
  641. // FIXME: bogus cast here.
  642. return new HashIterator<T>(type);
  643. }
  644. /**
  645. * A simplified, more efficient internal implementation of putAll(). clone()
  646. * should not call putAll or put, in order to be compatible with the JDK
  647. * implementation with respect to subclasses.
  648. *
  649. * @param m the map to initialize this from
  650. */
  651. void putAllInternal(Map<? extends K, ? extends V> m)
  652. {
  653. final Map<K,V> addMap = (Map<K,V>) m;
  654. final Iterator<Map.Entry<K,V>> it = addMap.entrySet().iterator();
  655. size = 0;
  656. while (it.hasNext())
  657. {
  658. final Map.Entry<K,V> e = it.next();
  659. size++;
  660. K key = e.getKey();
  661. int idx = hash(key);
  662. addEntry(key, e.getValue(), idx, false);
  663. }
  664. }
  665. /**
  666. * Increases the size of the HashMap and rehashes all keys to new
  667. * array indices; this is called when the addition of a new value
  668. * would cause size() &gt; threshold. Note that the existing Entry
  669. * objects are reused in the new hash table.
  670. *
  671. * <p>This is not specified, but the new size is twice the current size
  672. * plus one; this number is not always prime, unfortunately.
  673. */
  674. private void rehash()
  675. {
  676. HashEntry<K, V>[] oldBuckets = buckets;
  677. int newcapacity = (buckets.length * 2) + 1;
  678. threshold = (int) (newcapacity * loadFactor);
  679. buckets = (HashEntry<K, V>[]) new HashEntry[newcapacity];
  680. for (int i = oldBuckets.length - 1; i >= 0; i--)
  681. {
  682. HashEntry<K, V> e = oldBuckets[i];
  683. while (e != null)
  684. {
  685. int idx = hash(e.key);
  686. HashEntry<K, V> dest = buckets[idx];
  687. HashEntry<K, V> next = e.next;
  688. e.next = buckets[idx];
  689. buckets[idx] = e;
  690. e = next;
  691. }
  692. }
  693. }
  694. /**
  695. * Serializes this object to the given stream.
  696. *
  697. * @param s the stream to write to
  698. * @throws IOException if the underlying stream fails
  699. * @serialData the <i>capacity</i>(int) that is the length of the
  700. * bucket array, the <i>size</i>(int) of the hash map
  701. * are emitted first. They are followed by size entries,
  702. * each consisting of a key (Object) and a value (Object).
  703. */
  704. private void writeObject(ObjectOutputStream s) throws IOException
  705. {
  706. // Write the threshold and loadFactor fields.
  707. s.defaultWriteObject();
  708. s.writeInt(buckets.length);
  709. s.writeInt(size);
  710. // Avoid creating a wasted Set by creating the iterator directly.
  711. Iterator<HashEntry<K, V>> it = iterator(ENTRIES);
  712. while (it.hasNext())
  713. {
  714. HashEntry<K, V> entry = it.next();
  715. s.writeObject(entry.key);
  716. s.writeObject(entry.value);
  717. }
  718. }
  719. /**
  720. * Deserializes this object from the given stream.
  721. *
  722. * @param s the stream to read from
  723. * @throws ClassNotFoundException if the underlying stream fails
  724. * @throws IOException if the underlying stream fails
  725. * @serialData the <i>capacity</i>(int) that is the length of the
  726. * bucket array, the <i>size</i>(int) of the hash map
  727. * are emitted first. They are followed by size entries,
  728. * each consisting of a key (Object) and a value (Object).
  729. */
  730. private void readObject(ObjectInputStream s)
  731. throws IOException, ClassNotFoundException
  732. {
  733. // Read the threshold and loadFactor fields.
  734. s.defaultReadObject();
  735. // Read and use capacity, followed by key/value pairs.
  736. buckets = (HashEntry<K, V>[]) new HashEntry[s.readInt()];
  737. int len = s.readInt();
  738. size = len;
  739. while (len-- > 0)
  740. {
  741. Object key = s.readObject();
  742. addEntry((K) key, (V) s.readObject(), hash(key), false);
  743. }
  744. }
  745. /**
  746. * Iterate over HashMap's entries.
  747. * This implementation is parameterized to give a sequential view of
  748. * keys, values, or entries.
  749. *
  750. * @author Jon Zeppieri
  751. */
  752. private final class HashIterator<T> implements Iterator<T>
  753. {
  754. /**
  755. * The type of this Iterator: {@link #KEYS}, {@link #VALUES},
  756. * or {@link #ENTRIES}.
  757. */
  758. private final int type;
  759. /**
  760. * The number of modifications to the backing HashMap that we know about.
  761. */
  762. private int knownMod = modCount;
  763. /** The number of elements remaining to be returned by next(). */
  764. private int count = size;
  765. /** Current index in the physical hash table. */
  766. private int idx = buckets.length;
  767. /** The last Entry returned by a next() call. */
  768. private HashEntry last;
  769. /**
  770. * The next entry that should be returned by next(). It is set to something
  771. * if we're iterating through a bucket that contains multiple linked
  772. * entries. It is null if next() needs to find a new bucket.
  773. */
  774. private HashEntry next;
  775. /**
  776. * Construct a new HashIterator with the supplied type.
  777. * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
  778. */
  779. HashIterator(int type)
  780. {
  781. this.type = type;
  782. }
  783. /**
  784. * Returns true if the Iterator has more elements.
  785. * @return true if there are more elements
  786. */
  787. public boolean hasNext()
  788. {
  789. return count > 0;
  790. }
  791. /**
  792. * Returns the next element in the Iterator's sequential view.
  793. * @return the next element
  794. * @throws ConcurrentModificationException if the HashMap was modified
  795. * @throws NoSuchElementException if there is none
  796. */
  797. public T next()
  798. {
  799. if (knownMod != modCount)
  800. throw new ConcurrentModificationException();
  801. if (count == 0)
  802. throw new NoSuchElementException();
  803. count--;
  804. HashEntry e = next;
  805. while (e == null)
  806. e = buckets[--idx];
  807. next = e.next;
  808. last = e;
  809. if (type == VALUES)
  810. return (T) e.value;
  811. if (type == KEYS)
  812. return (T) e.key;
  813. return (T) e;
  814. }
  815. /**
  816. * Removes from the backing HashMap the last element which was fetched
  817. * with the <code>next()</code> method.
  818. * @throws ConcurrentModificationException if the HashMap was modified
  819. * @throws IllegalStateException if called when there is no last element
  820. */
  821. public void remove()
  822. {
  823. if (knownMod != modCount)
  824. throw new ConcurrentModificationException();
  825. if (last == null)
  826. throw new IllegalStateException();
  827. HashMap.this.remove(last.key);
  828. last = null;
  829. knownMod++;
  830. }
  831. }
  832. }