PageRenderTime 46ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/alibaba/fastjson/util/AntiCollisionHashMap.java

https://bitbucket.org/xiejuntao/xdesktop
Java | 1117 lines | 553 code | 119 blank | 445 comment | 149 complexity | d2de6f502d7bb8566ef435843f508007 MD5 | raw file
  1. package com.alibaba.fastjson.util;
  2. /*
  3. * %W% %E%
  4. *
  5. * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
  6. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  7. */
  8. import java.io.IOException;
  9. import java.io.Serializable;
  10. import java.util.AbstractCollection;
  11. import java.util.AbstractMap;
  12. import java.util.AbstractSet;
  13. import java.util.Collection;
  14. import java.util.Collections;
  15. import java.util.ConcurrentModificationException;
  16. import java.util.Hashtable;
  17. import java.util.Iterator;
  18. import java.util.Map;
  19. import java.util.NoSuchElementException;
  20. import java.util.Random;
  21. import java.util.Set;
  22. import java.util.TreeMap;
  23. /**
  24. * This class modfiy from jdk src.
  25. *
  26. * Hash table based implementation of the <tt>Map</tt> interface. This
  27. * implementation provides all of the optional map operations, and permits
  28. * <tt>null</tt> values and the <tt>null</tt> key. (The <tt>SafelyHashMap</tt>
  29. * class is roughly equivalent to <tt>Hashtable</tt>, except that it is
  30. * unsynchronized and permits nulls.) This class makes no guarantees as to the
  31. * order of the map; in particular, it does not guarantee that the order will
  32. * remain constant over time.
  33. *
  34. * <p>
  35. * This implementation provides constant-time performance for the basic
  36. * operations (<tt>get</tt> and <tt>put</tt>), assuming the hash function
  37. * disperses the elements properly among the buckets. Iteration over collection
  38. * views requires time proportional to the "capacity" of the
  39. * <tt>SafelyHashMap</tt> instance (the number of buckets) plus its size (the
  40. * number of key-value mappings). Thus, it's very important not to set the
  41. * initial capacity too high (or the load factor too low) if iteration
  42. * performance is important.
  43. *
  44. * <p>
  45. * An instance of <tt>SafelyHashMap</tt> has two parameters that affect its
  46. * performance: <i>initial capacity</i> and <i>load factor</i>. The
  47. * <i>capacity</i> is the number of buckets in the hash table, and the initial
  48. * capacity is simply the capacity at the time the hash table is created. The
  49. * <i>load factor</i> is a measure of how full the hash table is allowed to get
  50. * before its capacity is automatically increased. When the number of entries in
  51. * the hash table exceeds the product of the load factor and the current
  52. * capacity, the hash table is <i>rehashed</i> (that is, internal data
  53. * structures are rebuilt) so that the hash table has approximately twice the
  54. * number of buckets.
  55. *
  56. * <p>
  57. * As a general rule, the default load factor (.75) offers a good tradeoff
  58. * between time and space costs. Higher values decrease the space overhead but
  59. * increase the lookup cost (reflected in most of the operations of the
  60. * <tt>SafelyHashMap</tt> class, including <tt>get</tt> and <tt>put</tt>). The
  61. * expected number of entries in the map and its load factor should be taken
  62. * into account when setting its initial capacity, so as to minimize the number
  63. * of rehash operations. If the initial capacity is greater than the maximum
  64. * number of entries divided by the load factor, no rehash operations will ever
  65. * occur.
  66. *
  67. * <p>
  68. * If many mappings are to be stored in a <tt>SafelyHashMap</tt> instance,
  69. * creating it with a sufficiently large capacity will allow the mappings to be
  70. * stored more efficiently than letting it perform automatic rehashing as needed
  71. * to grow the table.
  72. *
  73. * <p>
  74. * <strong>Note that this implementation is not synchronized.</strong> If
  75. * multiple threads access a hash map concurrently, and at least one of the
  76. * threads modifies the map structurally, it <i>must</i> be synchronized
  77. * externally. (A structural modification is any operation that adds or deletes
  78. * one or more mappings; merely changing the value associated with a key that an
  79. * instance already contains is not a structural modification.) This is
  80. * typically accomplished by synchronizing on some object that naturally
  81. * encapsulates the map.
  82. *
  83. * If no such object exists, the map should be "wrapped" using the
  84. * {@link Collections#synchronizedMap Collections.synchronizedMap} method. This
  85. * is best done at creation time, to prevent accidental unsynchronized access to
  86. * the map:
  87. *
  88. * <pre>
  89. * Map m = Collections.synchronizedMap(new SafelyHashMap(...));
  90. * </pre>
  91. *
  92. * <p>
  93. * The iterators returned by all of this class's "collection view methods" are
  94. * <i>fail-fast</i>: if the map is structurally modified at any time after the
  95. * iterator is created, in any way except through the iterator's own
  96. * <tt>remove</tt> method, the iterator will throw a
  97. * {@link ConcurrentModificationException}. Thus, in the face of concurrent
  98. * modification, the iterator fails quickly and cleanly, rather than risking
  99. * arbitrary, non-deterministic behavior at an undetermined time in the future.
  100. *
  101. * <p>
  102. * Note that the fail-fast behavior of an iterator cannot be guaranteed as it
  103. * is, generally speaking, impossible to make any hard guarantees in the
  104. * presence of unsynchronized concurrent modification. Fail-fast iterators throw
  105. * <tt>ConcurrentModificationException</tt> on a best-effort basis. Therefore,
  106. * it would be wrong to write a program that depended on this exception for its
  107. * correctness: <i>the fail-fast behavior of iterators should be used only to
  108. * detect bugs.</i>
  109. *
  110. * <p>
  111. * This class is a member of the <a href="{@docRoot}
  112. * /../technotes/guides/collections/index.html"> Java Collections Framework</a>.
  113. *
  114. * @param <K>
  115. * the type of keys maintained by this map
  116. * @param <V>
  117. * the type of mapped values
  118. *
  119. * @author Axman
  120. * @author Doug Lea
  121. * @author Josh Bloch
  122. * @author Arthur van Hoff
  123. * @author Neal Gafter
  124. * @version %I%, %G%
  125. * @see Object#hashCode()
  126. * @see Collection
  127. * @see Map
  128. * @see TreeMap
  129. * @see Hashtable
  130. */
  131. @SuppressWarnings({"unchecked", "rawtypes"})
  132. public class AntiCollisionHashMap<K, V> extends AbstractMap<K, V> implements
  133. Map<K, V>, Cloneable, Serializable {
  134. transient volatile Set<K> keySet = null;
  135. transient volatile Collection<V> values = null;
  136. /**
  137. * The default initial capacity - MUST be a power of two.
  138. */
  139. static final int DEFAULT_INITIAL_CAPACITY = 16;
  140. /**
  141. * The maximum capacity, used if a higher value is implicitly specified by
  142. * either of the constructors with arguments. MUST be a power of two <=
  143. * 1<<30.
  144. */
  145. static final int MAXIMUM_CAPACITY = 1 << 30;
  146. /**
  147. * The load factor used when none specified in constructor.
  148. */
  149. static final float DEFAULT_LOAD_FACTOR = 0.75f;
  150. /**
  151. * The table, resized as necessary. Length MUST Always be a power of two.
  152. */
  153. transient Entry<K, V>[] table;
  154. /**
  155. * The number of key-value mappings contained in this map.
  156. */
  157. transient int size;
  158. /**
  159. * The next size value at which to resize (capacity * load factor).
  160. *
  161. * @serial
  162. */
  163. int threshold;
  164. /**
  165. * The load factor for the hash table.
  166. *
  167. * @serial
  168. */
  169. final float loadFactor;
  170. /**
  171. * The number of times this SafelyHashMap has been structurally modified
  172. * Structural modifications are those that change the number of mappings in
  173. * the SafelyHashMap or otherwise modify its internal structure (e.g.,
  174. * rehash). This field is used to make iterators on Collection-views of the
  175. * SafelyHashMap fail-fast. (See ConcurrentModificationException).
  176. */
  177. transient volatile int modCount;
  178. /**
  179. * Constructs an empty <tt>SafelyHashMap</tt> with the specified initial
  180. * capacity and load factor.
  181. *
  182. * @param initialCapacity
  183. * the initial capacity
  184. * @param loadFactor
  185. * the load factor
  186. * @throws IllegalArgumentException
  187. * if the initial capacity is negative or the load factor is
  188. * nonpositive
  189. */
  190. final static int M_MASK = 0x8765fed3;
  191. final static int SEED = -2128831035;
  192. final static int KEY = 16777619;
  193. final int random = new Random().nextInt(99999); // a fixed value in an instance
  194. private int hashString(String key) {
  195. int hash = SEED * random;
  196. for (int i = 0; i < key.length(); i++)
  197. hash = (hash * KEY) ^ key.charAt(i);
  198. return (hash ^ (hash >> 1)) & M_MASK;
  199. }
  200. public AntiCollisionHashMap(int initialCapacity, float loadFactor) {
  201. if (initialCapacity < 0)
  202. throw new IllegalArgumentException("Illegal initial capacity: "
  203. + initialCapacity);
  204. if (initialCapacity > MAXIMUM_CAPACITY)
  205. initialCapacity = MAXIMUM_CAPACITY;
  206. if (loadFactor <= 0 || Float.isNaN(loadFactor))
  207. throw new IllegalArgumentException("Illegal load factor: "
  208. + loadFactor);
  209. // Find a power of 2 >= initialCapacity
  210. int capacity = 1;
  211. while (capacity < initialCapacity)
  212. capacity <<= 1;
  213. this.loadFactor = loadFactor;
  214. threshold = (int) (capacity * loadFactor);
  215. table = new Entry[capacity];
  216. init();
  217. }
  218. /**
  219. * Constructs an empty <tt>SafelyHashMap</tt> with the specified initial
  220. * capacity and the default load factor (0.75).
  221. *
  222. * @param initialCapacity
  223. * the initial capacity.
  224. * @throws IllegalArgumentException
  225. * if the initial capacity is negative.
  226. */
  227. public AntiCollisionHashMap(int initialCapacity) {
  228. this(initialCapacity, DEFAULT_LOAD_FACTOR);
  229. }
  230. /**
  231. * Constructs an empty <tt>SafelyHashMap</tt> with the default initial
  232. * capacity (16) and the default load factor (0.75).
  233. */
  234. public AntiCollisionHashMap() {
  235. this.loadFactor = DEFAULT_LOAD_FACTOR;
  236. threshold = (int) (DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR);
  237. table = new Entry[DEFAULT_INITIAL_CAPACITY];
  238. init();
  239. }
  240. /**
  241. * Constructs a new <tt>SafelyHashMap</tt> with the same mappings as the
  242. * specified <tt>Map</tt>. The <tt>SafelyHashMap</tt> is created with
  243. * default load factor (0.75) and an initial capacity sufficient to hold the
  244. * mappings in the specified <tt>Map</tt>.
  245. *
  246. * @param m
  247. * the map whose mappings are to be placed in this map
  248. * @throws NullPointerException
  249. * if the specified map is null
  250. */
  251. public AntiCollisionHashMap(Map<? extends K, ? extends V> m) {
  252. this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
  253. DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
  254. putAllForCreate(m);
  255. }
  256. // internal utilities
  257. /**
  258. * Initialization hook for subclasses. This method is called in all
  259. * constructors and pseudo-constructors (clone, readObject) after
  260. * SafelyHashMap has been initialized but before any entries have been
  261. * inserted. (In the absence of this method, readObject would require
  262. * explicit knowledge of subclasses.)
  263. */
  264. void init() {
  265. }
  266. /**
  267. * Applies a supplemental hash function to a given hashCode, which defends
  268. * against poor quality hash functions. This is critical because
  269. * SafelyHashMap uses power-of-two length hash tables, that otherwise
  270. * encounter collisions for hashCodes that do not differ in lower bits.
  271. * Note: Null keys always map to hash 0, thus index 0.
  272. */
  273. static int hash(int h) {
  274. // This function ensures that hashCodes that differ only by
  275. // constant multiples at each bit position have a bounded
  276. // number of collisions (approximately 8 at default load factor).
  277. h = h * h;
  278. h ^= (h >>> 20) ^ (h >>> 12);
  279. return h ^ (h >>> 7) ^ (h >>> 4);
  280. }
  281. /**
  282. * Returns index for hash code h.
  283. */
  284. static int indexFor(int h, int length) {
  285. return h & (length - 1);
  286. }
  287. /**
  288. * Returns the number of key-value mappings in this map.
  289. *
  290. * @return the number of key-value mappings in this map
  291. */
  292. public int size() {
  293. return size;
  294. }
  295. /**
  296. * Returns <tt>true</tt> if this map contains no key-value mappings.
  297. *
  298. * @return <tt>true</tt> if this map contains no key-value mappings
  299. */
  300. public boolean isEmpty() {
  301. return size == 0;
  302. }
  303. /**
  304. * Returns the value to which the specified key is mapped, or {@code null}
  305. * if this map contains no mapping for the key.
  306. *
  307. * <p>
  308. * More formally, if this map contains a mapping from a key {@code k} to a
  309. * value {@code v} such that {@code (key==null ? k==null :
  310. * key.equals(k))}, then this method returns {@code v}; otherwise it returns
  311. * {@code null}. (There can be at most one such mapping.)
  312. *
  313. * <p>
  314. * A return value of {@code null} does not <i>necessarily</i> indicate that
  315. * the map contains no mapping for the key; it's also possible that the map
  316. * explicitly maps the key to {@code null}. The {@link #containsKey
  317. * containsKey} operation may be used to distinguish these two cases.
  318. *
  319. * @see #put(Object, Object)
  320. */
  321. public V get(Object key) {
  322. if (key == null)
  323. return getForNullKey();
  324. int hash = 0;
  325. if (key instanceof String)
  326. hash = hash(hashString((String) key));
  327. else
  328. hash = hash(key.hashCode());
  329. for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
  330. Object k;
  331. if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
  332. return e.value;
  333. }
  334. return null;
  335. }
  336. /**
  337. * Offloaded version of get() to look up null keys. Null keys map to index
  338. * 0. This null case is split out into separate methods for the sake of
  339. * performance in the two most commonly used operations (get and put), but
  340. * incorporated with conditionals in others.
  341. */
  342. private V getForNullKey() {
  343. for (Entry<K, V> e = table[0]; e != null; e = e.next) {
  344. if (e.key == null)
  345. return e.value;
  346. }
  347. return null;
  348. }
  349. /**
  350. * Returns <tt>true</tt> if this map contains a mapping for the specified
  351. * key.
  352. *
  353. * @param key
  354. * The key whose presence in this map is to be tested
  355. * @return <tt>true</tt> if this map contains a mapping for the specified
  356. * key.
  357. */
  358. public boolean containsKey(Object key) {
  359. return getEntry(key) != null;
  360. }
  361. /**
  362. * Returns the entry associated with the specified key in the SafelyHashMap.
  363. * Returns null if the SafelyHashMap contains no mapping for the key.
  364. */
  365. final Entry<K, V> getEntry(Object key) {
  366. int hash = (key == null) ? 0
  367. : (key instanceof String) ? hash(hashString((String) key))
  368. : hash(key.hashCode());
  369. for (Entry<K, V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) {
  370. Object k;
  371. if (e.hash == hash
  372. && ((k = e.key) == key || (key != null && key.equals(k))))
  373. return e;
  374. }
  375. return null;
  376. }
  377. /**
  378. * Associates the specified value with the specified key in this map. If the
  379. * map previously contained a mapping for the key, the old value is
  380. * replaced.
  381. *
  382. * @param key
  383. * key with which the specified value is to be associated
  384. * @param value
  385. * value to be associated with the specified key
  386. * @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
  387. * if there was no mapping for <tt>key</tt>. (A <tt>null</tt> return
  388. * can also indicate that the map previously associated
  389. * <tt>null</tt> with <tt>key</tt>.)
  390. */
  391. public V put(K key, V value) {
  392. if (key == null)
  393. return putForNullKey(value);
  394. int hash = 0;
  395. if (key instanceof String)
  396. hash = hash(hashString((String) key));
  397. else
  398. hash = hash(key.hashCode());
  399. int i = indexFor(hash, table.length);
  400. for (Entry<K, V> e = table[i]; e != null; e = e.next) {
  401. Object k;
  402. if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
  403. V oldValue = e.value;
  404. e.value = value;
  405. e.recordAccess(this);
  406. return oldValue;
  407. }
  408. }
  409. modCount++;
  410. addEntry(hash, key, value, i);
  411. return null;
  412. }
  413. /**
  414. * Offloaded version of put for null keys
  415. */
  416. private V putForNullKey(V value) {
  417. for (Entry<K, V> e = table[0]; e != null; e = e.next) {
  418. if (e.key == null) {
  419. V oldValue = e.value;
  420. e.value = value;
  421. e.recordAccess(this);
  422. return oldValue;
  423. }
  424. }
  425. modCount++;
  426. addEntry(0, null, value, 0);
  427. return null;
  428. }
  429. /**
  430. * This method is used instead of put by constructors and pseudoconstructors
  431. * (clone, readObject). It does not resize the table, check for
  432. * comodification, etc. It calls createEntry rather than addEntry.
  433. */
  434. private void putForCreate(K key, V value) {
  435. int hash = (key == null) ? 0
  436. : (key instanceof String) ? hash(hashString((String) key))
  437. : hash(key.hashCode());
  438. int i = indexFor(hash, table.length);
  439. /**
  440. * Look for preexisting entry for key. This will never happen for clone
  441. * or deserialize. It will only happen for construction if the input Map
  442. * is a sorted map whose ordering is inconsistent w/ equals.
  443. */
  444. for (Entry<K, V> e = table[i]; e != null; e = e.next) {
  445. Object k;
  446. if (e.hash == hash
  447. && ((k = e.key) == key || (key != null && key.equals(k)))) {
  448. e.value = value;
  449. return;
  450. }
  451. }
  452. createEntry(hash, key, value, i);
  453. }
  454. private void putAllForCreate(Map<? extends K, ? extends V> m) {
  455. for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m
  456. .entrySet().iterator(); i.hasNext();) {
  457. Map.Entry<? extends K, ? extends V> e = i.next();
  458. putForCreate(e.getKey(), e.getValue());
  459. }
  460. }
  461. /**
  462. * Rehashes the contents of this map into a new array with a larger
  463. * capacity. This method is called automatically when the number of keys in
  464. * this map reaches its threshold.
  465. *
  466. * If current capacity is MAXIMUM_CAPACITY, this method does not resize the
  467. * map, but sets threshold to Integer.MAX_VALUE. This has the effect of
  468. * preventing future calls.
  469. *
  470. * @param newCapacity
  471. * the new capacity, MUST be a power of two; must be greater than
  472. * current capacity unless current capacity is MAXIMUM_CAPACITY
  473. * (in which case value is irrelevant).
  474. */
  475. void resize(int newCapacity) {
  476. Entry<K, V>[] oldTable = table;
  477. int oldCapacity = oldTable.length;
  478. if (oldCapacity == MAXIMUM_CAPACITY) {
  479. threshold = Integer.MAX_VALUE;
  480. return;
  481. }
  482. Entry<K, V>[] newTable = new Entry[newCapacity];
  483. transfer(newTable);
  484. table = newTable;
  485. threshold = (int) (newCapacity * loadFactor);
  486. }
  487. /**
  488. * Transfers all entries from current table to newTable.
  489. */
  490. void transfer(Entry[] newTable) {
  491. Entry[] src = table;
  492. int newCapacity = newTable.length;
  493. for (int j = 0; j < src.length; j++) {
  494. Entry<K, V> e = src[j];
  495. if (e != null) {
  496. src[j] = null;
  497. do {
  498. Entry<K, V> next = e.next;
  499. int i = indexFor(e.hash, newCapacity);
  500. e.next = newTable[i];
  501. newTable[i] = e;
  502. e = next;
  503. } while (e != null);
  504. }
  505. }
  506. }
  507. /**
  508. * Copies all of the mappings from the specified map to this map. These
  509. * mappings will replace any mappings that this map had for any of the keys
  510. * currently in the specified map.
  511. *
  512. * @param m
  513. * mappings to be stored in this map
  514. * @throws NullPointerException
  515. * if the specified map is null
  516. */
  517. public void putAll(Map<? extends K, ? extends V> m) {
  518. int numKeysToBeAdded = m.size();
  519. if (numKeysToBeAdded == 0)
  520. return;
  521. /*
  522. * Expand the map if the map if the number of mappings to be added is
  523. * greater than or equal to threshold. This is conservative; the obvious
  524. * condition is (m.size() + size) >= threshold, but this condition could
  525. * result in a map with twice the appropriate capacity, if the keys to
  526. * be added overlap with the keys already in this map. By using the
  527. * conservative calculation, we subject ourself to at most one extra
  528. * resize.
  529. */
  530. if (numKeysToBeAdded > threshold) {
  531. int targetCapacity = (int) (numKeysToBeAdded / loadFactor + 1);
  532. if (targetCapacity > MAXIMUM_CAPACITY)
  533. targetCapacity = MAXIMUM_CAPACITY;
  534. int newCapacity = table.length;
  535. while (newCapacity < targetCapacity)
  536. newCapacity <<= 1;
  537. if (newCapacity > table.length)
  538. resize(newCapacity);
  539. }
  540. for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = m
  541. .entrySet().iterator(); i.hasNext();) {
  542. Map.Entry<? extends K, ? extends V> e = i.next();
  543. put(e.getKey(), e.getValue());
  544. }
  545. }
  546. /**
  547. * Removes the mapping for the specified key from this map if present.
  548. *
  549. * @param key
  550. * key whose mapping is to be removed from the map
  551. * @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
  552. * if there was no mapping for <tt>key</tt>. (A <tt>null</tt> return
  553. * can also indicate that the map previously associated
  554. * <tt>null</tt> with <tt>key</tt>.)
  555. */
  556. public V remove(Object key) {
  557. Entry<K, V> e = removeEntryForKey(key);
  558. return (e == null ? null : e.value);
  559. }
  560. /**
  561. * Removes and returns the entry associated with the specified key in the
  562. * SafelyHashMap. Returns null if the SafelyHashMap contains no mapping for
  563. * this key.
  564. */
  565. final Entry<K, V> removeEntryForKey(Object key) {
  566. int hash = (key == null) ? 0
  567. : (key instanceof String) ? hash(hashString((String) key))
  568. : hash(key.hashCode());
  569. int i = indexFor(hash, table.length);
  570. Entry<K, V> prev = table[i];
  571. Entry<K, V> e = prev;
  572. while (e != null) {
  573. Entry<K, V> next = e.next;
  574. Object k;
  575. if (e.hash == hash
  576. && ((k = e.key) == key || (key != null && key.equals(k)))) {
  577. modCount++;
  578. size--;
  579. if (prev == e)
  580. table[i] = next;
  581. else
  582. prev.next = next;
  583. e.recordRemoval(this);
  584. return e;
  585. }
  586. prev = e;
  587. e = next;
  588. }
  589. return e;
  590. }
  591. /**
  592. * Special version of remove for EntrySet.
  593. */
  594. final Entry<K, V> removeMapping(Object o) {
  595. if (!(o instanceof Map.Entry))
  596. return null;
  597. Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
  598. Object key = entry.getKey();
  599. int hash = (key == null) ? 0
  600. : (key instanceof String) ? hash(hashString((String) key))
  601. : hash(key.hashCode());
  602. int i = indexFor(hash, table.length);
  603. Entry<K, V> prev = table[i];
  604. Entry<K, V> e = prev;
  605. while (e != null) {
  606. Entry<K, V> next = e.next;
  607. if (e.hash == hash && e.equals(entry)) {
  608. modCount++;
  609. size--;
  610. if (prev == e)
  611. table[i] = next;
  612. else
  613. prev.next = next;
  614. e.recordRemoval(this);
  615. return e;
  616. }
  617. prev = e;
  618. e = next;
  619. }
  620. return e;
  621. }
  622. /**
  623. * Removes all of the mappings from this map. The map will be empty after
  624. * this call returns.
  625. */
  626. public void clear() {
  627. modCount++;
  628. Entry[] tab = table;
  629. for (int i = 0; i < tab.length; i++)
  630. tab[i] = null;
  631. size = 0;
  632. }
  633. /**
  634. * Returns <tt>true</tt> if this map maps one or more keys to the specified
  635. * value.
  636. *
  637. * @param value
  638. * value whose presence in this map is to be tested
  639. * @return <tt>true</tt> if this map maps one or more keys to the specified
  640. * value
  641. */
  642. public boolean containsValue(Object value) {
  643. if (value == null)
  644. return containsNullValue();
  645. Entry[] tab = table;
  646. for (int i = 0; i < tab.length; i++)
  647. for (Entry e = tab[i]; e != null; e = e.next)
  648. if (value.equals(e.value))
  649. return true;
  650. return false;
  651. }
  652. /**
  653. * Special-case code for containsValue with null argument
  654. */
  655. private boolean containsNullValue() {
  656. Entry[] tab = table;
  657. for (int i = 0; i < tab.length; i++)
  658. for (Entry e = tab[i]; e != null; e = e.next)
  659. if (e.value == null)
  660. return true;
  661. return false;
  662. }
  663. /**
  664. * Returns a shallow copy of this <tt>SafelyHashMap</tt> instance: the keys
  665. * and values themselves are not cloned.
  666. *
  667. * @return a shallow copy of this map
  668. */
  669. public Object clone() {
  670. AntiCollisionHashMap<K, V> result = null;
  671. try {
  672. result = (AntiCollisionHashMap<K, V>) super.clone();
  673. } catch (CloneNotSupportedException e) {
  674. // assert false;
  675. }
  676. result.table = new Entry[table.length];
  677. result.entrySet = null;
  678. result.modCount = 0;
  679. result.size = 0;
  680. result.init();
  681. result.putAllForCreate(this);
  682. return result;
  683. }
  684. static class Entry<K, V> implements Map.Entry<K, V> {
  685. final K key;
  686. V value;
  687. Entry<K, V> next;
  688. final int hash;
  689. /**
  690. * Creates new entry.
  691. */
  692. Entry(int h, K k, V v, Entry<K, V> n) {
  693. value = v;
  694. next = n;
  695. key = k;
  696. hash = h;
  697. }
  698. public final K getKey() {
  699. return key;
  700. }
  701. public final V getValue() {
  702. return value;
  703. }
  704. public final V setValue(V newValue) {
  705. V oldValue = value;
  706. value = newValue;
  707. return oldValue;
  708. }
  709. public final boolean equals(Object o) {
  710. if (!(o instanceof Map.Entry))
  711. return false;
  712. Map.Entry e = (Map.Entry) o;
  713. Object k1 = getKey();
  714. Object k2 = e.getKey();
  715. if (k1 == k2 || (k1 != null && k1.equals(k2))) {
  716. Object v1 = getValue();
  717. Object v2 = e.getValue();
  718. if (v1 == v2 || (v1 != null && v1.equals(v2)))
  719. return true;
  720. }
  721. return false;
  722. }
  723. public final int hashCode() {
  724. return (key == null ? 0 : key.hashCode())
  725. ^ (value == null ? 0 : value.hashCode());
  726. }
  727. public final String toString() {
  728. return getKey() + "=" + getValue();
  729. }
  730. /**
  731. * This method is invoked whenever the value in an entry is overwritten
  732. * by an invocation of put(k,v) for a key k that's already in the
  733. * SafelyHashMap.
  734. */
  735. void recordAccess(AntiCollisionHashMap<K, V> m) {
  736. }
  737. /**
  738. * This method is invoked whenever the entry is removed from the table.
  739. */
  740. void recordRemoval(AntiCollisionHashMap<K, V> m) {
  741. }
  742. }
  743. /**
  744. * Adds a new entry with the specified key, value and hash code to the
  745. * specified bucket. It is the responsibility of this method to resize the
  746. * table if appropriate.
  747. *
  748. * Subclass overrides this to alter the behavior of put method.
  749. */
  750. void addEntry(int hash, K key, V value, int bucketIndex) {
  751. Entry<K, V> e = table[bucketIndex];
  752. table[bucketIndex] = new Entry<K, V>(hash, key, value, e);
  753. if (size++ >= threshold)
  754. resize(2 * table.length);
  755. }
  756. /**
  757. * Like addEntry except that this version is used when creating entries as
  758. * part of Map construction or "pseudo-construction" (cloning,
  759. * deserialization). This version needn't worry about resizing the table.
  760. *
  761. * Subclass overrides this to alter the behavior of SafelyHashMap(Map),
  762. * clone, and readObject.
  763. */
  764. void createEntry(int hash, K key, V value, int bucketIndex) {
  765. Entry<K, V> e = table[bucketIndex];
  766. table[bucketIndex] = new Entry<K, V>(hash, key, value, e);
  767. size++;
  768. }
  769. private abstract class HashIterator<E> implements Iterator<E> {
  770. Entry<K, V> next; // next entry to return
  771. int expectedModCount; // For fast-fail
  772. int index; // current slot
  773. Entry<K, V> current; // current entry
  774. HashIterator() {
  775. expectedModCount = modCount;
  776. if (size > 0) { // advance to first entry
  777. Entry[] t = table;
  778. while (index < t.length && (next = t[index++]) == null)
  779. ;
  780. }
  781. }
  782. public final boolean hasNext() {
  783. return next != null;
  784. }
  785. final Entry<K, V> nextEntry() {
  786. if (modCount != expectedModCount)
  787. throw new ConcurrentModificationException();
  788. Entry<K, V> e = next;
  789. if (e == null)
  790. throw new NoSuchElementException();
  791. if ((next = e.next) == null) {
  792. Entry[] t = table;
  793. while (index < t.length && (next = t[index++]) == null)
  794. ;
  795. }
  796. current = e;
  797. return e;
  798. }
  799. public void remove() {
  800. if (current == null)
  801. throw new IllegalStateException();
  802. if (modCount != expectedModCount)
  803. throw new ConcurrentModificationException();
  804. Object k = current.key;
  805. current = null;
  806. AntiCollisionHashMap.this.removeEntryForKey(k);
  807. expectedModCount = modCount;
  808. }
  809. }
  810. private final class ValueIterator extends HashIterator<V> {
  811. public V next() {
  812. return nextEntry().value;
  813. }
  814. }
  815. private final class KeyIterator extends HashIterator<K> {
  816. public K next() {
  817. return nextEntry().getKey();
  818. }
  819. }
  820. private final class EntryIterator extends HashIterator<Map.Entry<K, V>> {
  821. public Map.Entry<K, V> next() {
  822. return nextEntry();
  823. }
  824. }
  825. // Subclass overrides these to alter behavior of views' iterator() method
  826. Iterator<K> newKeyIterator() {
  827. return new KeyIterator();
  828. }
  829. Iterator<V> newValueIterator() {
  830. return new ValueIterator();
  831. }
  832. Iterator<Map.Entry<K, V>> newEntryIterator() {
  833. return new EntryIterator();
  834. }
  835. // Views
  836. private transient Set<Map.Entry<K, V>> entrySet = null;
  837. /**
  838. * Returns a {@link Set} view of the keys contained in this map. The set is
  839. * backed by the map, so changes to the map are reflected in the set, and
  840. * vice-versa. If the map is modified while an iteration over the set is in
  841. * progress (except through the iterator's own <tt>remove</tt> operation),
  842. * the results of the iteration are undefined. The set supports element
  843. * removal, which removes the corresponding mapping from the map, via the
  844. * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
  845. * <tt>retainAll</tt>, and <tt>clear</tt> operations. It does not support
  846. * the <tt>add</tt> or <tt>addAll</tt> operations.
  847. */
  848. public Set<K> keySet() {
  849. Set<K> ks = keySet;
  850. return (ks != null ? ks : (keySet = new KeySet()));
  851. }
  852. private final class KeySet extends AbstractSet<K> {
  853. public Iterator<K> iterator() {
  854. return newKeyIterator();
  855. }
  856. public int size() {
  857. return size;
  858. }
  859. public boolean contains(Object o) {
  860. return containsKey(o);
  861. }
  862. public boolean remove(Object o) {
  863. return AntiCollisionHashMap.this.removeEntryForKey(o) != null;
  864. }
  865. public void clear() {
  866. AntiCollisionHashMap.this.clear();
  867. }
  868. }
  869. /**
  870. * Returns a {@link Collection} view of the values contained in this map.
  871. * The collection is backed by the map, so changes to the map are reflected
  872. * in the collection, and vice-versa. If the map is modified while an
  873. * iteration over the collection is in progress (except through the
  874. * iterator's own <tt>remove</tt> operation), the results of the iteration
  875. * are undefined. The collection supports element removal, which removes the
  876. * corresponding mapping from the map, via the <tt>Iterator.remove</tt>,
  877. * <tt>Collection.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
  878. * <tt>clear</tt> operations. It does not support the <tt>add</tt> or
  879. * <tt>addAll</tt> operations.
  880. */
  881. public Collection<V> values() {
  882. Collection<V> vs = values;
  883. return (vs != null ? vs : (values = new Values()));
  884. }
  885. private final class Values extends AbstractCollection<V> {
  886. public Iterator<V> iterator() {
  887. return newValueIterator();
  888. }
  889. public int size() {
  890. return size;
  891. }
  892. public boolean contains(Object o) {
  893. return containsValue(o);
  894. }
  895. public void clear() {
  896. AntiCollisionHashMap.this.clear();
  897. }
  898. }
  899. /**
  900. * Returns a {@link Set} view of the mappings contained in this map. The set
  901. * is backed by the map, so changes to the map are reflected in the set, and
  902. * vice-versa. If the map is modified while an iteration over the set is in
  903. * progress (except through the iterator's own <tt>remove</tt> operation, or
  904. * through the <tt>setValue</tt> operation on a map entry returned by the
  905. * iterator) the results of the iteration are undefined. The set supports
  906. * element removal, which removes the corresponding mapping from the map,
  907. * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>
  908. * , <tt>retainAll</tt> and <tt>clear</tt> operations. It does not support
  909. * the <tt>add</tt> or <tt>addAll</tt> operations.
  910. *
  911. * @return a set view of the mappings contained in this map
  912. */
  913. public Set<Map.Entry<K, V>> entrySet() {
  914. return entrySet0();
  915. }
  916. private Set<Map.Entry<K, V>> entrySet0() {
  917. Set<Map.Entry<K, V>> es = entrySet;
  918. return es != null ? es : (entrySet = new EntrySet());
  919. }
  920. private final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
  921. public Iterator<Map.Entry<K, V>> iterator() {
  922. return newEntryIterator();
  923. }
  924. public boolean contains(Object o) {
  925. if (!(o instanceof Map.Entry))
  926. return false;
  927. Map.Entry<K, V> e = (Map.Entry<K, V>) o;
  928. Entry<K, V> candidate = getEntry(e.getKey());
  929. return candidate != null && candidate.equals(e);
  930. }
  931. public boolean remove(Object o) {
  932. return removeMapping(o) != null;
  933. }
  934. public int size() {
  935. return size;
  936. }
  937. public void clear() {
  938. AntiCollisionHashMap.this.clear();
  939. }
  940. }
  941. /**
  942. * Save the state of the <tt>SafelyHashMap</tt> instance to a stream (i.e.,
  943. * serialize it).
  944. *
  945. * @serialData The <i>capacity</i> of the SafelyHashMap (the length of the
  946. * bucket array) is emitted (int), followed by the <i>size</i>
  947. * (an int, the number of key-value mappings), followed by the
  948. * key (Object) and value (Object) for each key-value mapping.
  949. * The key-value mappings are emitted in no particular order.
  950. */
  951. private void writeObject(java.io.ObjectOutputStream s) throws IOException {
  952. Iterator<Map.Entry<K, V>> i = (size > 0) ? entrySet0().iterator()
  953. : null;
  954. // Write out the threshold, loadfactor, and any hidden stuff
  955. s.defaultWriteObject();
  956. // Write out number of buckets
  957. s.writeInt(table.length);
  958. // Write out size (number of Mappings)
  959. s.writeInt(size);
  960. // Write out keys and values (alternating)
  961. if (i != null) {
  962. while (i.hasNext()) {
  963. Map.Entry<K, V> e = i.next();
  964. s.writeObject(e.getKey());
  965. s.writeObject(e.getValue());
  966. }
  967. }
  968. }
  969. private static final long serialVersionUID = 362498820763181265L;
  970. /**
  971. * Reconstitute the <tt>SafelyHashMap</tt> instance from a stream (i.e.,
  972. * deserialize it).
  973. */
  974. private void readObject(java.io.ObjectInputStream s) throws IOException,
  975. ClassNotFoundException {
  976. // Read in the threshold, loadfactor, and any hidden stuff
  977. s.defaultReadObject();
  978. // Read in number of buckets and allocate the bucket array;
  979. int numBuckets = s.readInt();
  980. table = new Entry[numBuckets];
  981. init(); // Give subclass a chance to do its thing.
  982. // Read in size (number of Mappings)
  983. int size = s.readInt();
  984. // Read the keys and values, and put the mappings in the SafelyHashMap
  985. for (int i = 0; i < size; i++) {
  986. K key = (K) s.readObject();
  987. V value = (V) s.readObject();
  988. putForCreate(key, value);
  989. }
  990. }
  991. // These methods are used when serializing HashSets
  992. int capacity() {
  993. return table.length;
  994. }
  995. float loadFactor() {
  996. return loadFactor;
  997. }
  998. }