3 import dstm2.AtomicArray;
4 import java.io.IOException;
5 import java.util.AbstractSet;
6 import java.util.ConcurrentModificationException;
7 import java.util.Iterator;
8 import java.util.NoSuchElementException;
10 import java.util.concurrent.atomic.AtomicInteger;
14 import dstm2.factory.Factory;
16 public class HashMap<V extends dstm2.AtomicSuperClass> implements Iterable<V> {
19 * The default initial capacity - MUST be a power of two.
21 static final int DEFAULT_INITIAL_CAPACITY = 4096;
23 * The maximum capacity, used if a higher value is implicitly specified
24 * by either of the constructors with arguments.
25 * MUST be a power of two <= 1<<30.
27 static final int MAXIMUM_CAPACITY = 1 << 30;
29 * The load factor used when none specified in constructor.
31 static final float DEFAULT_LOAD_FACTOR = 0.75f;
33 * The table, resized as necessary. Length MUST Always be a power of two.
35 //transient TEntry<V>[] table;
36 //dstm2.AtomicArray<TEntry> table;
37 //dstm2.AtomicArray<Wrapper> table;
38 tableHolder tableholder;
39 //dstm2.AtomicArray<Wrapper> wrappers;
40 final private Factory<tableHolder> factoryTable;
41 final private Factory<TEntry> factoryTEntry;
42 final private Factory<Wrapper> factorywrapper;
43 final private Factory<transactionalintfield> factoryint;
44 //transient Entry<K, V>[] table;
46 * The number of key-value mappings contained in this identity hash map.
49 // java.util.concurrent.atomic.AtomicInteger size;
51 * The capacity of the table
53 transactionalintfield capacity;
54 // transient int capacity;
56 * The next size value at which to resize (capacity * load factor).
59 transactionalintfield threshold;
60 //transactionalintfield size;
61 final int size = 2400;
64 * The load factor for the hash table.
68 final float loadFactor;
71 * The number of times this HashMap has been structurally modified
72 * Structural modifications are those that change the number of mappings in
73 * the HashMap or otherwise modify its internal structure (e.g.,
74 * rehash). This field is used to make iterators on Collection-views of
75 * the HashMap fail-fast. (See ConcurrentModificationException).
77 // transient volatile int modCount;
79 * Constructs an empty <tt>HashMap</tt> with the specified initial
80 * capacity and load factor.
82 * @param initialCapacity The initial capacity.
83 * @param loadFactor The load factor.
84 * @throws IllegalArgumentException if the initial capacity is negative
85 * or the load factor is nonpositive.
87 public HashMap(int initialCapacity, float loadFactor) {
88 // size = new AtomicInteger(0);
89 factoryTEntry = Thread.makeFactory(TEntry.class);
90 factorywrapper = Thread.makeFactory(Wrapper.class);
91 factoryTable = Thread.makeFactory(tableHolder.class);
92 factoryint = Thread.makeFactory(transactionalintfield.class);
93 if (initialCapacity < 0) {
94 throw new IllegalArgumentException("Illegal initial capacity: " +
97 if (initialCapacity > MAXIMUM_CAPACITY) {
98 initialCapacity = MAXIMUM_CAPACITY;
100 if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
101 throw new IllegalArgumentException("Illegal load factor: " +
104 // Find a power of 2 >= initialCapacity
107 while (tmpcapacity < initialCapacity) {
110 capacity = factoryint.create();
111 threshold = factoryint.create();
112 // size = factoryint.create();
116 capacity.setValue(tmpcapacity);
117 this.loadFactor = loadFactor;
118 threshold.setValue((int) (capacity.getValue() * loadFactor));
119 //threshold = (int) (capacity * loadFactor);
120 //table = new dstm2.AtomicArray<TEntry>(TEntry.class, capacity);
121 tableholder = factoryTable.create();
122 AtomicArray<Wrapper> table = new dstm2.AtomicArray<Wrapper>(Wrapper.class, capacity.getValue());
123 tableholder.setTable(table);
124 for (int i = 0; i < capacity.getValue(); i++) {
125 tableholder.getTable().set(i, factorywrapper.create());
126 tableholder.getTable().get(i).setTEntry(factoryTEntry.create());
127 //table.get(i).setTEntry(factoryTEntry.create());
129 // for(int i = 0; i < capacity; i++) {
130 // table[i] = factory.create();
132 //table = new Entry[capacity];
137 * Constructs an empty <tt>HashMap</tt> with the specified initial
138 * capacity and the default load factor (0.75).
140 * @param initialCapacity the initial capacity.
141 * @throws IllegalArgumentException if the initial capacity is negative.
143 public HashMap(int initialCapacity) {
144 this(initialCapacity, DEFAULT_LOAD_FACTOR);
148 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
149 * (16) and the default load factor (0.75).
152 this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
156 * Constructs a new <tt>HashMap</tt> with the same mappings as the
157 * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with
158 * default load factor (0.75) and an initial capacity sufficient to
159 * hold the mappings in the specified <tt>Map</tt>.
161 * @param m the map whose mappings are to be placed in this map.
162 * @throws NullPointerException if the specified map is null.
164 public HashMap(HashMap<? extends V> m) {
165 this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
166 DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
170 // internal utilities
172 * Initialization hook for subclasses. This method is called
173 * in all constructors and pseudo-constructors (clone, readObject)
174 * after HashMap has been initialized but before any entries have
175 * been inserted. (In the absence of this method, readObject would
176 * require explicit knowledge of subclasses.)
181 public dstm2.AtomicArray<Wrapper>/*dstm2.AtomicArray<TEntry>*/ getBuckets() {
182 return tableholder.getTable();
185 * Value representing null keys inside tables.
187 static final Object NULL_KEY = new Object();
190 * Returns internal representation for key. Use NULL_KEY if key is null.
192 static <T> T maskNull(T key) {
193 return key == null ? (T) NULL_KEY : key;
197 * Returns key represented by specified internal representation.
199 static <T> T unmaskNull(T key) {
200 return (key == NULL_KEY ? null : key);
203 * Whether to prefer the old supplemental hash function, for
204 * compatibility with broken applications that rely on the
205 * internal hashing order.
207 * Set to true only by hotspot when invoked via
208 * -XX:+UseNewHashFunction or -XX:+AggressiveOpts
210 private static final boolean useNewHash;
217 private static int oldHash(int h) {
225 private static int newHash(int h) {
226 // This function ensures that hashCodes that differ only by
227 // constant multiples at each bit position have a bounded
228 // number of collisions (approximately 8 at default load factor).
229 h ^= (h >>> 20) ^ (h >>> 12);
230 return h ^ (h >>> 7) ^ (h >>> 4);
234 * Applies a supplemental hash function to a given hashCode, which
235 * defends against poor quality hash functions. This is critical
236 * because HashMap uses power-of-two length hash tables, that
237 * otherwise encounter collisions for hashCodes that do not differ
240 public static int hash(int h) {
241 return useNewHash ? newHash(h) : oldHash(h);
244 static int hash(Object key) {
245 return hash(key.hashCode());
249 * Check for equality of non-null reference x and possibly-null y.
251 static boolean eq(Object x, Object y) {
252 return x == y || x.equals(y);
256 * Returns index for hash code h.
258 public static int indexFor(int h, int length) {
259 return h & (length - 1);
263 * Returns the number of key-value mappings in this map.
265 * @return the number of key-value mappings in this map.
268 return size;//.getValue();
272 * Returns <tt>true</tt> if this map contains no key-value mappings.
274 * @return <tt>true</tt> if this map contains no key-value mappings.
276 public boolean isEmpty() {
277 return size/*.getValue()*/ == 0;
281 * Returns the value to which the specified key is mapped in this identity
282 * hash map, or <tt>null</tt> if the map contains no mapping for this key.
283 * A return value of <tt>null</tt> does not <i>necessarily</i> indicate
284 * that the map contains no mapping for the key; it is also possible that
285 * the map explicitly maps the key to <tt>null</tt>. The
286 * <tt>containsKey</tt> method may be used to distinguish these two cases.
288 * @param key the key whose associated value is to be returned.
289 * @return the value to which this map maps the specified key, or
290 * <tt>null</tt> if the map contains no mapping for this key.
291 * @see #put(Object, Object)
293 public V get(int key) {
295 // return getForNullKey();
296 int hash = hash(key);
297 //for (TEntry<V> e = table.get(indexFor(hash, capacity))
299 for (TEntry<V> e = tableholder.getTable().get(indexFor(hash, capacity.getValue())).getTEntry();
302 if (e.getHash() == hash) {
309 // private V getForNullKey() {
310 // int hash = hash(NULL_KEY.hashCode());
311 // int i = indexFor(hash, capacity);
312 // TEntry<K,V> e = table[i];
313 // //Entry<K,V> e = table[i];
317 // if (e.getKey() == NULL_KEY)
318 // return e.getValue();
323 * Returns <tt>true</tt> if this map contains a mapping for the
326 * @param key The key whose presence in this map is to be tested
327 * @return <tt>true</tt> if this map contains a mapping for the specified
330 public boolean containsKey(int key) {
331 Object k = maskNull(key);
333 int i = indexFor(hash, capacity.getValue());
334 //TEntry<V> e = table.get(i);
335 TEntry<V> e = tableholder.getTable().get(i).getTEntry();
337 if (e.getHash() == hash) {
346 * Returns the entry associated with the specified key in the
347 * HashMap. Returns null if the HashMap contains no mapping
350 TEntry<V> getEntry(int key) {
351 int hash = hash(key);
352 int i = indexFor(hash, capacity.getValue());
353 //TEntry<V> e = table.get(i);
354 TEntry<V> e = tableholder.getTable().get(i).getTEntry();
355 while (e != null && !(e.getHash() == hash)) {
362 * Associates the specified value with the specified key in this map.
363 * If the map previously contained a mapping for this key, the old
366 * @param key key with which the specified value is to be associated.
367 * @param value value to be associated with the specified key.
368 * @return previous value associated with specified key, or <tt>null</tt>
369 * if there was no mapping for key. A <tt>null</tt> return can
370 * also indicate that the HashMap previously associated
371 * <tt>null</tt> with the specified key.
373 public V put(int key, V value) {
374 int hash = hash(key);
375 int i = indexFor(hash, capacity.getValue());
376 //for (TEntry<V> e = table.get(i); e != null; e = e.getNext()) {
378 for (TEntry<V> e = tableholder.getTable().get(i).getTEntry(); e != null; e = e.getNext()) {
379 if (e.getHash() == hash) {
380 V oldValue = e.getValue();
382 // e.recordAccess(this);
386 } catch (NullPointerException e) {
390 addEntry(hash, value, i);
395 * This method is used instead of put by constructors and
396 * pseudoconstructors (clone, readObject). It does not resize the table,
397 * check for comodification, etc. It calls createEntry rather than
400 private void putForCreate(int key, V value) {
401 int hash = hash(key);
402 int i = indexFor(hash, capacity.getValue());
405 * Look for preexisting entry for key. This will never happen for
406 * clone or deserialize. It will only happen for construction if the
407 * input Map is a sorted map whose ordering is inconsistent w/ equals.
409 //for (TEntry<V> e = table.get(i); e != null; e = e.getNext()) {
410 for (TEntry<V> e = tableholder.getTable().get(i).getTEntry(); e != null; e = e.getNext()) {
411 if (e.getHash() == hash) {
417 createEntry(hash, value, i);
420 void putAllForCreate(HashMap<? extends V> m) {
421 for (Iterator<? extends HashMap.TEntry<? extends V>> i = m.entrySet().iterator(); i.hasNext();) {
422 HashMap.TEntry<? extends V> e = i.next();
423 putForCreate(e.getHash(), e.getValue());
428 * Rehashes the contents of this map into a new array with a
429 * larger capacity. This method is called automatically when the
430 * number of keys in this map reaches its threshold.
432 * If current capacity is MAXIMUM_CAPACITY, this method does not
433 * resize the map, but sets threshold to Integer.MAX_VALUE.
434 * This has the effect of preventing future calls.
436 * @param newCapacity the new capacity, MUST be a power of two;
437 * must be greater than current capacity unless current
438 * capacity is MAXIMUM_CAPACITY (in which case value
441 void resize(int newCapacity) {
442 //dstm2.AtomicArray<TEntry> oldTable = table;
443 //dstm2.AtomicArray<Wrapper> oldTable = tableholder.getTable();
444 int oldCapacity = capacity.getValue();
445 if (oldCapacity == MAXIMUM_CAPACITY) {
446 threshold.setValue(Integer.MAX_VALUE);
450 //dstm2.AtomicArray<TEntry> newTable = new dstm2.AtomicArray<TEntry>(TEntry.class, newCapacity);
451 dstm2.AtomicArray<Wrapper> newTable = new dstm2.AtomicArray<Wrapper>(Wrapper.class, newCapacity);
452 for (int i = 0; i < newCapacity; i++) {
453 if (i < capacity.getValue()) {
454 newTable.set(i, tableholder.getTable().get(i)/*factorywrapper.create()*/);
455 newTable.get(i).setTEntry(factoryTEntry.create());
457 newTable.set(i, factorywrapper.create());
458 newTable.get(i).setTEntry(factoryTEntry.create());
461 //capacity.setValue(newCapacity);
462 transfer(newTable, newCapacity);
463 tableholder.setTable(newTable);
464 threshold.setValue((int) (newCapacity * loadFactor));
465 capacity.setValue(newCapacity);
469 * Transfer all entries from current table to newTable.
471 //void transfer(dstm2.AtomicArray<TEntry> newTable, int nc) {
472 void transfer(dstm2.AtomicArray<Wrapper> newTable, int nc) {
473 //dstm2.AtomicArray<TEntry> src = table;
474 //dstm2.AtomicArray<Wrapper> src = table;
475 int newCapacity = nc;
476 for (int j = 0; j < capacity.getValue(); j++) {
477 TEntry<V> e = tableholder.getTable().get(j).getTEntry();
478 //TEntry<V> e = src.get(j);
480 tableholder.getTable().set(j, null);
482 /*TEntry<V> next = e.getNext();
483 int i = indexFor(e.getHash(), newCapacity);
484 e.setNext(newTable.get(i));
488 TEntry<V> next = e.getNext();
489 int i = indexFor(e.getHash(), newCapacity);
490 e.setNext(newTable.get(i).getTEntry());
491 //e.setNext(tableholder.getTable().get(i).getTEntry());
492 newTable.get(i).setTEntry(e);
493 //tableholder.getTable().get(i).setTEntry(e);
501 * Copies all of the mappings from the specified map to this map
502 * These mappings will replace any mappings that
503 * this map had for any of the keys currently in the specified map.
505 * @param m mappings to be stored in this map.
506 * @throws NullPointerException if the specified map is null.
508 public void putAll(HashMap<? extends V> m) {
509 int numKeysToBeAdded = m.size();
510 if (numKeysToBeAdded == 0) {
514 * Expand the map if the map if the number of mappings to be added
515 * is greater than or equal to threshold. This is conservative; the
516 * obvious condition is (m.size() + size) >= threshold, but this
517 * condition could result in a map with twice the appropriate capacity,
518 * if the keys to be added overlap with the keys already in this map.
519 * By using the conservative calculation, we subject ourself
520 * to at most one extra resize.
523 if (numKeysToBeAdded > threshold.getValue()) {
524 int targetCapacity = (int) (numKeysToBeAdded / loadFactor + 1);
525 if (targetCapacity > MAXIMUM_CAPACITY) {
526 targetCapacity = MAXIMUM_CAPACITY;
528 int newCapacity = capacity.getValue();
529 while (newCapacity < targetCapacity) {
532 if (newCapacity > capacity.getValue()) {
537 for (Iterator<? extends HashMap.TEntry<? extends V>> i = m.entrySet().iterator(); i.hasNext();) {
538 HashMap.TEntry<? extends V> e = i.next();
539 put(e.getHash(), e.getValue());
544 * Removes the mapping for this key from this map if present.
546 * @param key key whose mapping is to be removed from the map.
547 * @return previous value associated with specified key, or <tt>null</tt>
548 * if there was no mapping for key. A <tt>null</tt> return can
549 * also indicate that the map previously associated <tt>null</tt>
550 * with the specified key.
552 public V remove(int key) {
553 TEntry<V> e = removeEntryForKey(key);
554 return (e == null ? null : e.getValue());
558 * Removes and returns the entry associated with the specified key
559 * in the HashMap. Returns null if the HashMap contains no mapping
562 TEntry<V> removeEntryForKey(int key) {
563 int hash = hash(key);
564 int i = indexFor(hash, capacity.getValue());
565 //TEntry<V> prev = table.get(i);
566 TEntry<V> prev = tableholder.getTable().get(i).getTEntry();
570 TEntry<V> next = e.getNext();
571 if (e.getHash() == hash) {
573 // size.setValue(size.getValue() - 1);
576 tableholder.getTable().get(i).setTEntry(next);
577 //table.set(i, next);
580 // e.recordRemoval(this);
592 * Special version of remove for EntrySet.
594 TEntry<V> removeMapping(TEntry<V> o) {
597 int hash = hash(o.getHash());
598 int i = indexFor(hash, capacity.getValue());
599 //TEntry<V> prev = table.get(i);
600 TEntry<V> prev = tableholder.getTable().get(i).getTEntry();
604 TEntry<V> next = e.getNext();
605 if (e.getHash() == hash) {
607 // size.setValue(size.getValue() - 1);
610 //table.set(i, next);
611 tableholder.getTable().get(i).setTEntry(next);
614 // e.recordRemoval(this);
626 * Removes all mappings from this map.
628 public void clear() {
630 //dstm2.AtomicArray<TEntry> tab = table;
632 for (int i = 0; i < capacity.getValue(); i++) {
633 tableholder.getTable().set(i, null);
640 * Returns <tt>true</tt> if this map maps one or more keys to the
643 * @param value value whose presence in this map is to be tested.
644 * @return <tt>true</tt> if this map maps one or more keys to the
647 public boolean containsValue(Object value) {
649 return containsNullValue();
651 //dstm2.AtomicArray<TEntry> tab = table;
652 //dstm2.AtomicArray<Wrapper> tab = table;
653 for (int i = 0; i < capacity.getValue(); i++) {
654 //for (TEntry e = tab.get(i); e != null; e = e.getNext()) {
655 for (TEntry e = tableholder.getTable().get(i).getTEntry(); e != null; e = e.getNext()) {
656 if (value.equals(e.getValue())) {
665 * Special-case code for containsValue with null argument
667 private boolean containsNullValue() {
668 //dstm2.AtomicArray<TEntry> tab = table;
669 //dstm2.AtomicArray<Wrapper> tab = table;
670 for (int i = 0; i < capacity.getValue(); i++) {
671 for (TEntry e = tableholder.getTable().get(i).getTEntry(); e != null; e = e.getNext()) {
672 //for (TEntry e = tab.get(i); e != null; e = e.getNext()) {
673 if (e.getValue() == null) {
682 public interface transactionalintfield {
686 void setValue(int val);
690 public interface tableHolder {
692 dstm2.AtomicArray<Wrapper> getTable();
694 void setTable(dstm2.AtomicArray<Wrapper> table);
698 public interface Wrapper {
702 void setTEntry(TEntry n);
706 public interface TEntry<V> {
718 void setNext(TEntry<V> n);
722 * Add a new entry with the specified key, value and hash code to
723 * the specified bucket. It is the responsibility of this
724 * method to resize the table if appropriate.
726 * Subclass overrides this to alter the behavior of put method.
728 void addEntry(int hash, V value, int bucketIndex) {
729 //TEntry<V> e = table.get(bucketIndex);
730 TEntry<V> e = tableholder.getTable().get(bucketIndex).getTEntry();
731 TEntry<V> n = factoryTEntry.create();
736 //table.set(bucketIndex, n);
737 tableholder.getTable().get(bucketIndex).setTEntry(n);
738 //should be uncommmented
740 //size.setValue(size.getValue() + 1);
742 //synchronized (this) {
743 // if (size >= threshold.getValue()) {
744 // resize(2 * capacity.getValue());
751 * Like addEntry except that this version is used when creating entries
752 * as part of Map construction or "pseudo-construction" (cloning,
753 * deserialization). This version needn't worry about resizing the table.
755 * Subclass overrides this to alter the behavior of HashMap(Map),
756 * clone, and readObject.
758 void createEntry(int hash, V value, int bucketIndex) {
759 //TEntry<V> e = table.get(bucketIndex);
760 TEntry<V> e = tableholder.getTable().get(bucketIndex).getTEntry();
761 TEntry<V> n = factoryTEntry.create();
765 //table.set(bucketIndex, n);
766 tableholder.getTable().get(bucketIndex).setTEntry(n);
768 //size.setValue(size.getValue() + 1);
771 private abstract class HashIterator<E> implements Iterator<E> {
773 TEntry<V> next; // next entry to return
775 int expectedModCount; // For fast-fail
777 int index; // current slot
779 TEntry<V> current; // current entry
783 // expectedModCount = modCount;
784 //dstm2.AtomicArray<TEntry> t = table;
785 //dstm2.AtomicArray<Wrapper> t = table;
786 int i = capacity.getValue();
789 //if (size.getValue() != 0) { // advance to first entry
790 //while (i > 0 && (n = t.get(--i)) == null);
792 while (i > 0 && (n = tableholder.getTable().get(--i).getTEntry()) == null);
798 public boolean hasNext() {
802 TEntry<V> nextEntry() {
803 // if (modCount != expectedModCount) {
804 // throw new ConcurrentModificationException();
808 throw new NoSuchElementException();
810 TEntry<V> n = e.getNext();
811 //dstm2.AtomicArray<TEntry> t = table;
812 //dstm2.AtomicArray<Wrapper> t = table;
814 while (n == null && i > 0) {
816 n = tableholder.getTable().get(--i).getTEntry();
823 public void remove() {
824 if (current == null) {
825 throw new IllegalStateException();
827 // if (modCount != expectedModCount) {
828 // throw new ConcurrentModificationException();
830 int k = current.getHash();
832 HashMap.this.removeEntryForKey(k);
833 // expectedModCount = modCount;
837 private class ValueIterator extends HashIterator<V> {
840 return nextEntry().getValue();
844 private class KeyIterator extends HashIterator<Integer> {
846 public Integer next() {
847 return nextEntry().getHash();
851 // private class EntryIterator extends HashIterator<Map.Entry<K,V>> {
852 // public Map.Entry<K,V> next() {
853 // return nextEntry();
857 // Subclass overrides these to alter behavior of views' iterator() method
858 public Iterator<Integer> newKeyIterator() {
859 return new KeyIterator();
862 public Iterator<V> newValueIterator() {
863 return new ValueIterator();
865 // Iterator<Map.Entry<K,V>> newEntryIterator() {
866 // return new EntryIterator();
869 private transient Set<HashMap.TEntry<V>> entrySet = null;
871 private class KeySet extends AbstractSet<Integer> {
873 public Iterator<Integer> iterator() {
874 return newKeyIterator();
878 return size;/*.getValue();*/
881 public boolean contains(Integer o) {
882 return containsKey(o);
885 public boolean remove(Integer o) {
886 return HashMap.this.removeEntryForKey(o) != null;
889 public void clear() {
890 HashMap.this.clear();
895 * Returns a collection view of the mappings contained in this map. Each
896 * element in the returned collection is a <tt>Map.Entry</tt>. The
897 * collection is backed by the map, so changes to the map are reflected in
898 * the collection, and vice-versa. The collection supports element
899 * removal, which removes the corresponding mapping from the map, via the
900 * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
901 * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
902 * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
904 * @return a collection view of the mappings contained in this map.
907 public Set<HashMap.TEntry<V>> entrySet() {
908 Set<HashMap.TEntry<V>> es = entrySet;
909 return (es != null ? es : (entrySet = (Set<HashMap.TEntry<V>>) (Set) new EntrySet()));
912 private class EntrySet {//extends AbstractSet/*<Map.Entry<K,V>>*/ {
913 // public Iterator/*<Map.Entry<K,V>>*/ iterator() {
914 // return newEntryIterator();
917 public boolean contains(HashMap.TEntry<V> o) {
918 HashMap.TEntry<V> e = (HashMap.TEntry<V>) o;
919 TEntry<V> candidate = getEntry(e.getHash());
920 return candidate != null && candidate.equals(e);
923 public boolean remove(HashMap.TEntry<V> o) {
924 return removeMapping(o) != null;
928 return size;//.getValue();
931 public void clear() {
932 HashMap.this.clear();
937 * Save the state of the <tt>HashMap</tt> instance to a stream (i.e.,
940 * @serialData The <i>capacity</i> of the HashMap (the length of the
941 * bucket array) is emitted (int), followed by the
942 * <i>size</i> of the HashMap (the number of key-value
943 * mappings), followed by the key (Object) and value (Object)
944 * for each key-value mapping represented by the HashMap
945 * The key-value mappings are emitted in the order that they
946 * are returned by <tt>entrySet().iterator()</tt>.
949 private void writeObject(java.io.ObjectOutputStream s)
951 Iterator<HashMap.TEntry<V>> i = entrySet().iterator();
953 // Write out the threshold, loadfactor, and any hidden stuff
954 s.defaultWriteObject();
956 // Write out number of buckets
957 s.writeInt(capacity.getValue());
959 // Write out size (number of Mappings)
960 s.writeInt(size/*.getValue()*/);
962 // Write out keys and values (alternating)
963 while (i.hasNext()) {
964 HashMap.TEntry<V> e = i.next();
965 s.writeObject(e.getHash());
966 s.writeObject(e.getValue());
969 private static final long serialVersionUID = 362498820763181265L;
972 * Reconstitute the <tt>HashMap</tt> instance from a stream (i.e.,
975 private void readObject(java.io.ObjectInputStream s)
976 throws IOException, ClassNotFoundException {
977 // Read in the threshold, loadfactor, and any hidden stuff
978 s.defaultReadObject();
980 // Read in number of buckets and allocate the bucket array;
981 int numBuckets = s.readInt();
982 tableholder.setTable(new dstm2.AtomicArray(TEntry.class, numBuckets));
984 init(); // Give subclass a chance to do its thing.
986 // Read in size (number of Mappings)
987 int size = s.readInt();
989 // Read the keys and values, and put the mappings in the HashMap
990 for (int i = 0; i < size; i++) {
991 int key = (Integer) s.readObject();
992 V value = (V) s.readObject();
993 putForCreate(key, value);
997 // These methods are used when serializing HashSets
999 return capacity.getValue();
1002 float loadFactor() {
1006 public int getCapacity() {
1007 return capacity.getValue();
1010 public Iterator<V> iterator() {
1011 return new Iterator<V>() {
1014 //public TEntry<V> cursor = table.get(tableIndex);
1015 public TEntry<V> cursor = tableholder.getTable().get(tableIndex).getTEntry();
1017 public boolean hasNext() {
1018 return cursor != null;
1022 TEntry<V> node = cursor;
1023 cursor = cursor.getNext();
1024 while (cursor == null) {
1026 if (tableIndex < capacity.getValue()) {
1027 //cursor = table.get(tableIndex);
1028 cursor = tableholder.getTable().get(tableIndex).getTEntry();
1031 return node.getValue();
1034 public void remove() {
1035 throw new UnsupportedOperationException();