1// GenericsNote: Converted -- However, null keys will now be represented in the internal structures, a big change.
2/*
3 *  Copyright 2003-2004 The Apache Software Foundation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17package org.jivesoftware.smack.util.collections;
18
19import java.io.IOException;
20import java.io.ObjectInputStream;
21import java.io.ObjectOutputStream;
22import java.util.*;
23
24/**
25 * An abstract implementation of a hash-based map which provides numerous points for
26 * subclasses to override.
27 * <p/>
28 * This class implements all the features necessary for a subclass hash-based map.
29 * Key-value entries are stored in instances of the <code>HashEntry</code> class,
30 * which can be overridden and replaced. The iterators can similarly be replaced,
31 * without the need to replace the KeySet, EntrySet and Values view classes.
32 * <p/>
33 * Overridable methods are provided to change the default hashing behaviour, and
34 * to change how entries are added to and removed from the map. Hopefully, all you
35 * need for unusual subclasses is here.
36 * <p/>
37 * NOTE: From Commons Collections 3.1 this class extends AbstractMap.
38 * This is to provide backwards compatibility for ReferenceMap between v3.0 and v3.1.
39 * This extends clause will be removed in v4.0.
40 *
41 * @author java util HashMap
42 * @author Matt Hall, John Watkinson, Stephen Colebourne
43 * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
44 * @since Commons Collections 3.0
45 */
46public class AbstractHashedMap <K,V> extends AbstractMap<K, V> implements IterableMap<K, V> {
47
48    protected static final String NO_NEXT_ENTRY = "No next() entry in the iteration";
49    protected static final String NO_PREVIOUS_ENTRY = "No previous() entry in the iteration";
50    protected static final String REMOVE_INVALID = "remove() can only be called once after next()";
51    protected static final String GETKEY_INVALID = "getKey() can only be called after next() and before remove()";
52    protected static final String GETVALUE_INVALID = "getValue() can only be called after next() and before remove()";
53    protected static final String SETVALUE_INVALID = "setValue() can only be called after next() and before remove()";
54
55    /**
56     * The default capacity to use
57     */
58    protected static final int DEFAULT_CAPACITY = 16;
59    /**
60     * The default threshold to use
61     */
62    protected static final int DEFAULT_THRESHOLD = 12;
63    /**
64     * The default load factor to use
65     */
66    protected static final float DEFAULT_LOAD_FACTOR = 0.75f;
67    /**
68     * The maximum capacity allowed
69     */
70    protected static final int MAXIMUM_CAPACITY = 1 << 30;
71    /**
72     * An object for masking null
73     */
74    protected static final Object NULL = new Object();
75
76    /**
77     * Load factor, normally 0.75
78     */
79    protected transient float loadFactor;
80    /**
81     * The size of the map
82     */
83    protected transient int size;
84    /**
85     * Map entries
86     */
87    protected transient HashEntry<K, V>[] data;
88    /**
89     * Size at which to rehash
90     */
91    protected transient int threshold;
92    /**
93     * Modification count for iterators
94     */
95    protected transient int modCount;
96    /**
97     * Entry set
98     */
99    protected transient EntrySet<K, V> entrySet;
100    /**
101     * Key set
102     */
103    protected transient KeySet<K, V> keySet;
104    /**
105     * Values
106     */
107    protected transient Values<K, V> values;
108
109    /**
110     * Constructor only used in deserialization, do not use otherwise.
111     */
112    protected AbstractHashedMap() {
113        super();
114    }
115
116    /**
117     * Constructor which performs no validation on the passed in parameters.
118     *
119     * @param initialCapacity the initial capacity, must be a power of two
120     * @param loadFactor      the load factor, must be &gt; 0.0f and generally &lt; 1.0f
121     * @param threshold       the threshold, must be sensible
122     */
123    protected AbstractHashedMap(int initialCapacity, float loadFactor, int threshold) {
124        super();
125        this.loadFactor = loadFactor;
126        this.data = new HashEntry[initialCapacity];
127        this.threshold = threshold;
128        init();
129    }
130
131    /**
132     * Constructs a new, empty map with the specified initial capacity and
133     * default load factor.
134     *
135     * @param initialCapacity the initial capacity
136     * @throws IllegalArgumentException if the initial capacity is less than one
137     */
138    protected AbstractHashedMap(int initialCapacity) {
139        this(initialCapacity, DEFAULT_LOAD_FACTOR);
140    }
141
142    /**
143     * Constructs a new, empty map with the specified initial capacity and
144     * load factor.
145     *
146     * @param initialCapacity the initial capacity
147     * @param loadFactor      the load factor
148     * @throws IllegalArgumentException if the initial capacity is less than one
149     * @throws IllegalArgumentException if the load factor is less than or equal to zero
150     */
151    protected AbstractHashedMap(int initialCapacity, float loadFactor) {
152        super();
153        if (initialCapacity < 1) {
154            throw new IllegalArgumentException("Initial capacity must be greater than 0");
155        }
156        if (loadFactor <= 0.0f || Float.isNaN(loadFactor)) {
157            throw new IllegalArgumentException("Load factor must be greater than 0");
158        }
159        this.loadFactor = loadFactor;
160        this.threshold = calculateThreshold(initialCapacity, loadFactor);
161        initialCapacity = calculateNewCapacity(initialCapacity);
162        this.data = new HashEntry[initialCapacity];
163        init();
164    }
165
166    /**
167     * Constructor copying elements from another map.
168     *
169     * @param map the map to copy
170     * @throws NullPointerException if the map is null
171     */
172    protected AbstractHashedMap(Map<? extends K, ? extends V> map) {
173        this(Math.max(2 * map.size(), DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
174        putAll(map);
175    }
176
177    /**
178     * Initialise subclasses during construction, cloning or deserialization.
179     */
180    protected void init() {
181    }
182
183    //-----------------------------------------------------------------------
184    /**
185     * Gets the value mapped to the key specified.
186     *
187     * @param key the key
188     * @return the mapped value, null if no match
189     */
190    public V get(Object key) {
191        int hashCode = hash((key == null) ? NULL : key);
192        HashEntry<K, V> entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
193        while (entry != null) {
194            if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) {
195                return entry.getValue();
196            }
197            entry = entry.next;
198        }
199        return null;
200    }
201
202    /**
203     * Gets the size of the map.
204     *
205     * @return the size
206     */
207    public int size() {
208        return size;
209    }
210
211    /**
212     * Checks whether the map is currently empty.
213     *
214     * @return true if the map is currently size zero
215     */
216    public boolean isEmpty() {
217        return (size == 0);
218    }
219
220    //-----------------------------------------------------------------------
221    /**
222     * Checks whether the map contains the specified key.
223     *
224     * @param key the key to search for
225     * @return true if the map contains the key
226     */
227    public boolean containsKey(Object key) {
228        int hashCode = hash((key == null) ? NULL : key);
229        HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
230        while (entry != null) {
231            if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
232                return true;
233            }
234            entry = entry.next;
235        }
236        return false;
237    }
238
239    /**
240     * Checks whether the map contains the specified value.
241     *
242     * @param value the value to search for
243     * @return true if the map contains the value
244     */
245    public boolean containsValue(Object value) {
246        if (value == null) {
247            for (int i = 0, isize = data.length; i < isize; i++) {
248                HashEntry entry = data[i];
249                while (entry != null) {
250                    if (entry.getValue() == null) {
251                        return true;
252                    }
253                    entry = entry.next;
254                }
255            }
256        } else {
257            for (int i = 0, isize = data.length; i < isize; i++) {
258                HashEntry entry = data[i];
259                while (entry != null) {
260                    if (isEqualValue(value, entry.getValue())) {
261                        return true;
262                    }
263                    entry = entry.next;
264                }
265            }
266        }
267        return false;
268    }
269
270    //-----------------------------------------------------------------------
271    /**
272     * Puts a key-value mapping into this map.
273     *
274     * @param key   the key to add
275     * @param value the value to add
276     * @return the value previously mapped to this key, null if none
277     */
278    public V put(K key, V value) {
279        int hashCode = hash((key == null) ? NULL : key);
280        int index = hashIndex(hashCode, data.length);
281        HashEntry<K, V> entry = data[index];
282        while (entry != null) {
283            if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
284                V oldValue = entry.getValue();
285                updateEntry(entry, value);
286                return oldValue;
287            }
288            entry = entry.next;
289        }
290        addMapping(index, hashCode, key, value);
291        return null;
292    }
293
294    /**
295     * Puts all the values from the specified map into this map.
296     * <p/>
297     * This implementation iterates around the specified map and
298     * uses {@link #put(Object, Object)}.
299     *
300     * @param map the map to add
301     * @throws NullPointerException if the map is null
302     */
303    public void putAll(Map<? extends K, ? extends V> map) {
304        int mapSize = map.size();
305        if (mapSize == 0) {
306            return;
307        }
308        int newSize = (int) ((size + mapSize) / loadFactor + 1);
309        ensureCapacity(calculateNewCapacity(newSize));
310        // Have to cast here because of compiler inference problems.
311        for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
312            Map.Entry<? extends K, ? extends V> entry = (Map.Entry<? extends K, ? extends V>) it.next();
313            put(entry.getKey(), entry.getValue());
314        }
315    }
316
317    /**
318     * Removes the specified mapping from this map.
319     *
320     * @param key the mapping to remove
321     * @return the value mapped to the removed key, null if key not in map
322     */
323    public V remove(Object key) {
324        int hashCode = hash((key == null) ? NULL : key);
325        int index = hashIndex(hashCode, data.length);
326        HashEntry<K, V> entry = data[index];
327        HashEntry<K, V> previous = null;
328        while (entry != null) {
329            if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
330                V oldValue = entry.getValue();
331                removeMapping(entry, index, previous);
332                return oldValue;
333            }
334            previous = entry;
335            entry = entry.next;
336        }
337        return null;
338    }
339
340    /**
341     * Clears the map, resetting the size to zero and nullifying references
342     * to avoid garbage collection issues.
343     */
344    public void clear() {
345        modCount++;
346        HashEntry[] data = this.data;
347        for (int i = data.length - 1; i >= 0; i--) {
348            data[i] = null;
349        }
350        size = 0;
351    }
352
353    /**
354     * Gets the hash code for the key specified.
355     * This implementation uses the additional hashing routine from JDK1.4.
356     * Subclasses can override this to return alternate hash codes.
357     *
358     * @param key the key to get a hash code for
359     * @return the hash code
360     */
361    protected int hash(Object key) {
362        // same as JDK 1.4
363        int h = key.hashCode();
364        h += ~(h << 9);
365        h ^= (h >>> 14);
366        h += (h << 4);
367        h ^= (h >>> 10);
368        return h;
369    }
370
371    /**
372     * Compares two keys, in internal converted form, to see if they are equal.
373     * This implementation uses the equals method.
374     * Subclasses can override this to match differently.
375     *
376     * @param key1 the first key to compare passed in from outside
377     * @param key2 the second key extracted from the entry via <code>entry.key</code>
378     * @return true if equal
379     */
380    protected boolean isEqualKey(Object key1, Object key2) {
381        return (key1 == key2 || ((key1 != null) && key1.equals(key2)));
382    }
383
384    /**
385     * Compares two values, in external form, to see if they are equal.
386     * This implementation uses the equals method and assumes neither value is null.
387     * Subclasses can override this to match differently.
388     *
389     * @param value1 the first value to compare passed in from outside
390     * @param value2 the second value extracted from the entry via <code>getValue()</code>
391     * @return true if equal
392     */
393    protected boolean isEqualValue(Object value1, Object value2) {
394        return (value1 == value2 || value1.equals(value2));
395    }
396
397    /**
398     * Gets the index into the data storage for the hashCode specified.
399     * This implementation uses the least significant bits of the hashCode.
400     * Subclasses can override this to return alternate bucketing.
401     *
402     * @param hashCode the hash code to use
403     * @param dataSize the size of the data to pick a bucket from
404     * @return the bucket index
405     */
406    protected int hashIndex(int hashCode, int dataSize) {
407        return hashCode & (dataSize - 1);
408    }
409
410    //-----------------------------------------------------------------------
411    /**
412     * Gets the entry mapped to the key specified.
413     * <p/>
414     * This method exists for subclasses that may need to perform a multi-step
415     * process accessing the entry. The public methods in this class don't use this
416     * method to gain a small performance boost.
417     *
418     * @param key the key
419     * @return the entry, null if no match
420     */
421    protected HashEntry<K, V> getEntry(Object key) {
422        int hashCode = hash((key == null) ? NULL : key);
423        HashEntry<K, V> entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
424        while (entry != null) {
425            if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
426                return entry;
427            }
428            entry = entry.next;
429        }
430        return null;
431    }
432
433    //-----------------------------------------------------------------------
434    /**
435     * Updates an existing key-value mapping to change the value.
436     * <p/>
437     * This implementation calls <code>setValue()</code> on the entry.
438     * Subclasses could override to handle changes to the map.
439     *
440     * @param entry    the entry to update
441     * @param newValue the new value to store
442     */
443    protected void updateEntry(HashEntry<K, V> entry, V newValue) {
444        entry.setValue(newValue);
445    }
446
447    /**
448     * Reuses an existing key-value mapping, storing completely new data.
449     * <p/>
450     * This implementation sets all the data fields on the entry.
451     * Subclasses could populate additional entry fields.
452     *
453     * @param entry     the entry to update, not null
454     * @param hashIndex the index in the data array
455     * @param hashCode  the hash code of the key to add
456     * @param key       the key to add
457     * @param value     the value to add
458     */
459    protected void reuseEntry(HashEntry<K, V> entry, int hashIndex, int hashCode, K key, V value) {
460        entry.next = data[hashIndex];
461        entry.hashCode = hashCode;
462        entry.key = key;
463        entry.value = value;
464    }
465
466    //-----------------------------------------------------------------------
467    /**
468     * Adds a new key-value mapping into this map.
469     * <p/>
470     * This implementation calls <code>createEntry()</code>, <code>addEntry()</code>
471     * and <code>checkCapacity()</code>.
472     * It also handles changes to <code>modCount</code> and <code>size</code>.
473     * Subclasses could override to fully control adds to the map.
474     *
475     * @param hashIndex the index into the data array to store at
476     * @param hashCode  the hash code of the key to add
477     * @param key       the key to add
478     * @param value     the value to add
479     */
480    protected void addMapping(int hashIndex, int hashCode, K key, V value) {
481        modCount++;
482        HashEntry<K, V> entry = createEntry(data[hashIndex], hashCode, key, value);
483        addEntry(entry, hashIndex);
484        size++;
485        checkCapacity();
486    }
487
488    /**
489     * Creates an entry to store the key-value data.
490     * <p/>
491     * This implementation creates a new HashEntry instance.
492     * Subclasses can override this to return a different storage class,
493     * or implement caching.
494     *
495     * @param next     the next entry in sequence
496     * @param hashCode the hash code to use
497     * @param key      the key to store
498     * @param value    the value to store
499     * @return the newly created entry
500     */
501    protected HashEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
502        return new HashEntry<K, V>(next, hashCode, key, value);
503    }
504
505    /**
506     * Adds an entry into this map.
507     * <p/>
508     * This implementation adds the entry to the data storage table.
509     * Subclasses could override to handle changes to the map.
510     *
511     * @param entry     the entry to add
512     * @param hashIndex the index into the data array to store at
513     */
514    protected void addEntry(HashEntry<K, V> entry, int hashIndex) {
515        data[hashIndex] = entry;
516    }
517
518    //-----------------------------------------------------------------------
519    /**
520     * Removes a mapping from the map.
521     * <p/>
522     * This implementation calls <code>removeEntry()</code> and <code>destroyEntry()</code>.
523     * It also handles changes to <code>modCount</code> and <code>size</code>.
524     * Subclasses could override to fully control removals from the map.
525     *
526     * @param entry     the entry to remove
527     * @param hashIndex the index into the data structure
528     * @param previous  the previous entry in the chain
529     */
530    protected void removeMapping(HashEntry<K, V> entry, int hashIndex, HashEntry<K, V> previous) {
531        modCount++;
532        removeEntry(entry, hashIndex, previous);
533        size--;
534        destroyEntry(entry);
535    }
536
537    /**
538     * Removes an entry from the chain stored in a particular index.
539     * <p/>
540     * This implementation removes the entry from the data storage table.
541     * The size is not updated.
542     * Subclasses could override to handle changes to the map.
543     *
544     * @param entry     the entry to remove
545     * @param hashIndex the index into the data structure
546     * @param previous  the previous entry in the chain
547     */
548    protected void removeEntry(HashEntry<K, V> entry, int hashIndex, HashEntry<K, V> previous) {
549        if (previous == null) {
550            data[hashIndex] = entry.next;
551        } else {
552            previous.next = entry.next;
553        }
554    }
555
556    /**
557     * Kills an entry ready for the garbage collector.
558     * <p/>
559     * This implementation prepares the HashEntry for garbage collection.
560     * Subclasses can override this to implement caching (override clear as well).
561     *
562     * @param entry the entry to destroy
563     */
564    protected void destroyEntry(HashEntry<K, V> entry) {
565        entry.next = null;
566        entry.key = null;
567        entry.value = null;
568    }
569
570    //-----------------------------------------------------------------------
571    /**
572     * Checks the capacity of the map and enlarges it if necessary.
573     * <p/>
574     * This implementation uses the threshold to check if the map needs enlarging
575     */
576    protected void checkCapacity() {
577        if (size >= threshold) {
578            int newCapacity = data.length * 2;
579            if (newCapacity <= MAXIMUM_CAPACITY) {
580                ensureCapacity(newCapacity);
581            }
582        }
583    }
584
585    /**
586     * Changes the size of the data structure to the capacity proposed.
587     *
588     * @param newCapacity the new capacity of the array (a power of two, less or equal to max)
589     */
590    protected void ensureCapacity(int newCapacity) {
591        int oldCapacity = data.length;
592        if (newCapacity <= oldCapacity) {
593            return;
594        }
595        if (size == 0) {
596            threshold = calculateThreshold(newCapacity, loadFactor);
597            data = new HashEntry[newCapacity];
598        } else {
599            HashEntry<K, V> oldEntries[] = data;
600            HashEntry<K, V> newEntries[] = new HashEntry[newCapacity];
601
602            modCount++;
603            for (int i = oldCapacity - 1; i >= 0; i--) {
604                HashEntry<K, V> entry = oldEntries[i];
605                if (entry != null) {
606                    oldEntries[i] = null;  // gc
607                    do {
608                        HashEntry<K, V> next = entry.next;
609                        int index = hashIndex(entry.hashCode, newCapacity);
610                        entry.next = newEntries[index];
611                        newEntries[index] = entry;
612                        entry = next;
613                    } while (entry != null);
614                }
615            }
616            threshold = calculateThreshold(newCapacity, loadFactor);
617            data = newEntries;
618        }
619    }
620
621    /**
622     * Calculates the new capacity of the map.
623     * This implementation normalizes the capacity to a power of two.
624     *
625     * @param proposedCapacity the proposed capacity
626     * @return the normalized new capacity
627     */
628    protected int calculateNewCapacity(int proposedCapacity) {
629        int newCapacity = 1;
630        if (proposedCapacity > MAXIMUM_CAPACITY) {
631            newCapacity = MAXIMUM_CAPACITY;
632        } else {
633            while (newCapacity < proposedCapacity) {
634                newCapacity <<= 1;  // multiply by two
635            }
636            if (newCapacity > MAXIMUM_CAPACITY) {
637                newCapacity = MAXIMUM_CAPACITY;
638            }
639        }
640        return newCapacity;
641    }
642
643    /**
644     * Calculates the new threshold of the map, where it will be resized.
645     * This implementation uses the load factor.
646     *
647     * @param newCapacity the new capacity
648     * @param factor      the load factor
649     * @return the new resize threshold
650     */
651    protected int calculateThreshold(int newCapacity, float factor) {
652        return (int) (newCapacity * factor);
653    }
654
655    //-----------------------------------------------------------------------
656    /**
657     * Gets the <code>next</code> field from a <code>HashEntry</code>.
658     * Used in subclasses that have no visibility of the field.
659     *
660     * @param entry the entry to query, must not be null
661     * @return the <code>next</code> field of the entry
662     * @throws NullPointerException if the entry is null
663     * @since Commons Collections 3.1
664     */
665    protected HashEntry<K, V> entryNext(HashEntry<K, V> entry) {
666        return entry.next;
667    }
668
669    /**
670     * Gets the <code>hashCode</code> field from a <code>HashEntry</code>.
671     * Used in subclasses that have no visibility of the field.
672     *
673     * @param entry the entry to query, must not be null
674     * @return the <code>hashCode</code> field of the entry
675     * @throws NullPointerException if the entry is null
676     * @since Commons Collections 3.1
677     */
678    protected int entryHashCode(HashEntry<K, V> entry) {
679        return entry.hashCode;
680    }
681
682    /**
683     * Gets the <code>key</code> field from a <code>HashEntry</code>.
684     * Used in subclasses that have no visibility of the field.
685     *
686     * @param entry the entry to query, must not be null
687     * @return the <code>key</code> field of the entry
688     * @throws NullPointerException if the entry is null
689     * @since Commons Collections 3.1
690     */
691    protected K entryKey(HashEntry<K, V> entry) {
692        return entry.key;
693    }
694
695    /**
696     * Gets the <code>value</code> field from a <code>HashEntry</code>.
697     * Used in subclasses that have no visibility of the field.
698     *
699     * @param entry the entry to query, must not be null
700     * @return the <code>value</code> field of the entry
701     * @throws NullPointerException if the entry is null
702     * @since Commons Collections 3.1
703     */
704    protected V entryValue(HashEntry<K, V> entry) {
705        return entry.value;
706    }
707
708    //-----------------------------------------------------------------------
709    /**
710     * Gets an iterator over the map.
711     * Changes made to the iterator affect this map.
712     * <p/>
713     * A MapIterator returns the keys in the map. It also provides convenient
714     * methods to get the key and value, and set the value.
715     * It avoids the need to create an entrySet/keySet/values object.
716     * It also avoids creating the Map.Entry object.
717     *
718     * @return the map iterator
719     */
720    public MapIterator<K, V> mapIterator() {
721        if (size == 0) {
722            return EmptyMapIterator.INSTANCE;
723        }
724        return new HashMapIterator<K, V>(this);
725    }
726
727    /**
728     * MapIterator implementation.
729     */
730    protected static class HashMapIterator <K,V> extends HashIterator<K, V> implements MapIterator<K, V> {
731
732        protected HashMapIterator(AbstractHashedMap<K, V> parent) {
733            super(parent);
734        }
735
736        public K next() {
737            return super.nextEntry().getKey();
738        }
739
740        public K getKey() {
741            HashEntry<K, V> current = currentEntry();
742            if (current == null) {
743                throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
744            }
745            return current.getKey();
746        }
747
748        public V getValue() {
749            HashEntry<K, V> current = currentEntry();
750            if (current == null) {
751                throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
752            }
753            return current.getValue();
754        }
755
756        public V setValue(V value) {
757            HashEntry<K, V> current = currentEntry();
758            if (current == null) {
759                throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
760            }
761            return current.setValue(value);
762        }
763    }
764
765    //-----------------------------------------------------------------------
766    /**
767     * Gets the entrySet view of the map.
768     * Changes made to the view affect this map.
769     * To simply iterate through the entries, use {@link #mapIterator()}.
770     *
771     * @return the entrySet view
772     */
773    public Set<Map.Entry<K, V>> entrySet() {
774        if (entrySet == null) {
775            entrySet = new EntrySet<K, V>(this);
776        }
777        return entrySet;
778    }
779
780    /**
781     * Creates an entry set iterator.
782     * Subclasses can override this to return iterators with different properties.
783     *
784     * @return the entrySet iterator
785     */
786    protected Iterator<Map.Entry<K, V>> createEntrySetIterator() {
787        if (size() == 0) {
788            return EmptyIterator.INSTANCE;
789        }
790        return new EntrySetIterator<K, V>(this);
791    }
792
793    /**
794     * EntrySet implementation.
795     */
796    protected static class EntrySet <K,V> extends AbstractSet<Map.Entry<K, V>> {
797        /**
798         * The parent map
799         */
800        protected final AbstractHashedMap<K, V> parent;
801
802        protected EntrySet(AbstractHashedMap<K, V> parent) {
803            super();
804            this.parent = parent;
805        }
806
807        public int size() {
808            return parent.size();
809        }
810
811        public void clear() {
812            parent.clear();
813        }
814
815        public boolean contains(Map.Entry<K, V> entry) {
816            Map.Entry<K, V> e = entry;
817            Entry<K, V> match = parent.getEntry(e.getKey());
818            return (match != null && match.equals(e));
819        }
820
821        public boolean remove(Object obj) {
822            if (obj instanceof Map.Entry == false) {
823                return false;
824            }
825            if (contains(obj) == false) {
826                return false;
827            }
828            Map.Entry<K, V> entry = (Map.Entry<K, V>) obj;
829            K key = entry.getKey();
830            parent.remove(key);
831            return true;
832        }
833
834        public Iterator<Map.Entry<K, V>> iterator() {
835            return parent.createEntrySetIterator();
836        }
837    }
838
839    /**
840     * EntrySet iterator.
841     */
842    protected static class EntrySetIterator <K,V> extends HashIterator<K, V> implements Iterator<Map.Entry<K, V>> {
843
844        protected EntrySetIterator(AbstractHashedMap<K, V> parent) {
845            super(parent);
846        }
847
848        public HashEntry<K, V> next() {
849            return super.nextEntry();
850        }
851    }
852
853    //-----------------------------------------------------------------------
854    /**
855     * Gets the keySet view of the map.
856     * Changes made to the view affect this map.
857     * To simply iterate through the keys, use {@link #mapIterator()}.
858     *
859     * @return the keySet view
860     */
861    public Set<K> keySet() {
862        if (keySet == null) {
863            keySet = new KeySet<K, V>(this);
864        }
865        return keySet;
866    }
867
868    /**
869     * Creates a key set iterator.
870     * Subclasses can override this to return iterators with different properties.
871     *
872     * @return the keySet iterator
873     */
874    protected Iterator<K> createKeySetIterator() {
875        if (size() == 0) {
876            return EmptyIterator.INSTANCE;
877        }
878        return new KeySetIterator<K, V>(this);
879    }
880
881    /**
882     * KeySet implementation.
883     */
884    protected static class KeySet <K,V> extends AbstractSet<K> {
885        /**
886         * The parent map
887         */
888        protected final AbstractHashedMap<K, V> parent;
889
890        protected KeySet(AbstractHashedMap<K, V> parent) {
891            super();
892            this.parent = parent;
893        }
894
895        public int size() {
896            return parent.size();
897        }
898
899        public void clear() {
900            parent.clear();
901        }
902
903        public boolean contains(Object key) {
904            return parent.containsKey(key);
905        }
906
907        public boolean remove(Object key) {
908            boolean result = parent.containsKey(key);
909            parent.remove(key);
910            return result;
911        }
912
913        public Iterator<K> iterator() {
914            return parent.createKeySetIterator();
915        }
916    }
917
918    /**
919     * KeySet iterator.
920     */
921    protected static class KeySetIterator <K,V> extends HashIterator<K, V> implements Iterator<K> {
922
923        protected KeySetIterator(AbstractHashedMap<K, V> parent) {
924            super(parent);
925        }
926
927        public K next() {
928            return super.nextEntry().getKey();
929        }
930    }
931
932    //-----------------------------------------------------------------------
933    /**
934     * Gets the values view of the map.
935     * Changes made to the view affect this map.
936     * To simply iterate through the values, use {@link #mapIterator()}.
937     *
938     * @return the values view
939     */
940    public Collection<V> values() {
941        if (values == null) {
942            values = new Values(this);
943        }
944        return values;
945    }
946
947    /**
948     * Creates a values iterator.
949     * Subclasses can override this to return iterators with different properties.
950     *
951     * @return the values iterator
952     */
953    protected Iterator<V> createValuesIterator() {
954        if (size() == 0) {
955            return EmptyIterator.INSTANCE;
956        }
957        return new ValuesIterator<K, V>(this);
958    }
959
960    /**
961     * Values implementation.
962     */
963    protected static class Values <K,V> extends AbstractCollection<V> {
964        /**
965         * The parent map
966         */
967        protected final AbstractHashedMap<K, V> parent;
968
969        protected Values(AbstractHashedMap<K, V> parent) {
970            super();
971            this.parent = parent;
972        }
973
974        public int size() {
975            return parent.size();
976        }
977
978        public void clear() {
979            parent.clear();
980        }
981
982        public boolean contains(Object value) {
983            return parent.containsValue(value);
984        }
985
986        public Iterator<V> iterator() {
987            return parent.createValuesIterator();
988        }
989    }
990
991    /**
992     * Values iterator.
993     */
994    protected static class ValuesIterator <K,V> extends HashIterator<K, V> implements Iterator<V> {
995
996        protected ValuesIterator(AbstractHashedMap<K, V> parent) {
997            super(parent);
998        }
999
1000        public V next() {
1001            return super.nextEntry().getValue();
1002        }
1003    }
1004
1005    //-----------------------------------------------------------------------
1006    /**
1007     * HashEntry used to store the data.
1008     * <p/>
1009     * If you subclass <code>AbstractHashedMap</code> but not <code>HashEntry</code>
1010     * then you will not be able to access the protected fields.
1011     * The <code>entryXxx()</code> methods on <code>AbstractHashedMap</code> exist
1012     * to provide the necessary access.
1013     */
1014    protected static class HashEntry <K,V> implements Map.Entry<K, V>, KeyValue<K, V> {
1015        /**
1016         * The next entry in the hash chain
1017         */
1018        protected HashEntry<K, V> next;
1019        /**
1020         * The hash code of the key
1021         */
1022        protected int hashCode;
1023        /**
1024         * The key
1025         */
1026        private K key;
1027        /**
1028         * The value
1029         */
1030        private V value;
1031
1032        protected HashEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
1033            super();
1034            this.next = next;
1035            this.hashCode = hashCode;
1036            this.key = key;
1037            this.value = value;
1038        }
1039
1040        public K getKey() {
1041            return key;
1042        }
1043
1044        public void setKey(K key) {
1045            this.key = key;
1046        }
1047
1048        public V getValue() {
1049            return value;
1050        }
1051
1052        public V setValue(V value) {
1053            V old = this.value;
1054            this.value = value;
1055            return old;
1056        }
1057
1058        public boolean equals(Object obj) {
1059            if (obj == this) {
1060                return true;
1061            }
1062            if (obj instanceof Map.Entry == false) {
1063                return false;
1064            }
1065            Map.Entry other = (Map.Entry) obj;
1066            return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
1067        }
1068
1069        public int hashCode() {
1070            return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
1071        }
1072
1073        public String toString() {
1074            return new StringBuilder().append(getKey()).append('=').append(getValue()).toString();
1075        }
1076    }
1077
1078    /**
1079     * Base Iterator
1080     */
1081    protected static abstract class HashIterator <K,V> {
1082
1083        /**
1084         * The parent map
1085         */
1086        protected final AbstractHashedMap parent;
1087        /**
1088         * The current index into the array of buckets
1089         */
1090        protected int hashIndex;
1091        /**
1092         * The last returned entry
1093         */
1094        protected HashEntry<K, V> last;
1095        /**
1096         * The next entry
1097         */
1098        protected HashEntry<K, V> next;
1099        /**
1100         * The modification count expected
1101         */
1102        protected int expectedModCount;
1103
1104        protected HashIterator(AbstractHashedMap<K, V> parent) {
1105            super();
1106            this.parent = parent;
1107            HashEntry<K, V>[] data = parent.data;
1108            int i = data.length;
1109            HashEntry<K, V> next = null;
1110            while (i > 0 && next == null) {
1111                next = data[--i];
1112            }
1113            this.next = next;
1114            this.hashIndex = i;
1115            this.expectedModCount = parent.modCount;
1116        }
1117
1118        public boolean hasNext() {
1119            return (next != null);
1120        }
1121
1122        protected HashEntry<K, V> nextEntry() {
1123            if (parent.modCount != expectedModCount) {
1124                throw new ConcurrentModificationException();
1125            }
1126            HashEntry<K, V> newCurrent = next;
1127            if (newCurrent == null) {
1128                throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
1129            }
1130            HashEntry<K, V>[] data = parent.data;
1131            int i = hashIndex;
1132            HashEntry<K, V> n = newCurrent.next;
1133            while (n == null && i > 0) {
1134                n = data[--i];
1135            }
1136            next = n;
1137            hashIndex = i;
1138            last = newCurrent;
1139            return newCurrent;
1140        }
1141
1142        protected HashEntry<K, V> currentEntry() {
1143            return last;
1144        }
1145
1146        public void remove() {
1147            if (last == null) {
1148                throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
1149            }
1150            if (parent.modCount != expectedModCount) {
1151                throw new ConcurrentModificationException();
1152            }
1153            parent.remove(last.getKey());
1154            last = null;
1155            expectedModCount = parent.modCount;
1156        }
1157
1158        public String toString() {
1159            if (last != null) {
1160                return "Iterator[" + last.getKey() + "=" + last.getValue() + "]";
1161            } else {
1162                return "Iterator[]";
1163            }
1164        }
1165    }
1166
1167    //-----------------------------------------------------------------------
1168    /**
1169     * Writes the map data to the stream. This method must be overridden if a
1170     * subclass must be setup before <code>put()</code> is used.
1171     * <p/>
1172     * Serialization is not one of the JDK's nicest topics. Normal serialization will
1173     * initialise the superclass before the subclass. Sometimes however, this isn't
1174     * what you want, as in this case the <code>put()</code> method on read can be
1175     * affected by subclass state.
1176     * <p/>
1177     * The solution adopted here is to serialize the state data of this class in
1178     * this protected method. This method must be called by the
1179     * <code>writeObject()</code> of the first serializable subclass.
1180     * <p/>
1181     * Subclasses may override if they have a specific field that must be present
1182     * on read before this implementation will work. Generally, the read determines
1183     * what must be serialized here, if anything.
1184     *
1185     * @param out the output stream
1186     */
1187    protected void doWriteObject(ObjectOutputStream out) throws IOException {
1188        out.writeFloat(loadFactor);
1189        out.writeInt(data.length);
1190        out.writeInt(size);
1191        for (MapIterator it = mapIterator(); it.hasNext();) {
1192            out.writeObject(it.next());
1193            out.writeObject(it.getValue());
1194        }
1195    }
1196
1197    /**
1198     * Reads the map data from the stream. This method must be overridden if a
1199     * subclass must be setup before <code>put()</code> is used.
1200     * <p/>
1201     * Serialization is not one of the JDK's nicest topics. Normal serialization will
1202     * initialise the superclass before the subclass. Sometimes however, this isn't
1203     * what you want, as in this case the <code>put()</code> method on read can be
1204     * affected by subclass state.
1205     * <p/>
1206     * The solution adopted here is to deserialize the state data of this class in
1207     * this protected method. This method must be called by the
1208     * <code>readObject()</code> of the first serializable subclass.
1209     * <p/>
1210     * Subclasses may override if the subclass has a specific field that must be present
1211     * before <code>put()</code> or <code>calculateThreshold()</code> will work correctly.
1212     *
1213     * @param in the input stream
1214     */
1215    protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
1216        loadFactor = in.readFloat();
1217        int capacity = in.readInt();
1218        int size = in.readInt();
1219        init();
1220        data = new HashEntry[capacity];
1221        for (int i = 0; i < size; i++) {
1222            K key = (K) in.readObject();
1223            V value = (V) in.readObject();
1224            put(key, value);
1225        }
1226        threshold = calculateThreshold(data.length, loadFactor);
1227    }
1228
1229    //-----------------------------------------------------------------------
1230    /**
1231     * Clones the map without cloning the keys or values.
1232     * <p/>
1233     * To implement <code>clone()</code>, a subclass must implement the
1234     * <code>Cloneable</code> interface and make this method public.
1235     *
1236     * @return a shallow clone
1237     */
1238    protected Object clone() {
1239        try {
1240            AbstractHashedMap cloned = (AbstractHashedMap) super.clone();
1241            cloned.data = new HashEntry[data.length];
1242            cloned.entrySet = null;
1243            cloned.keySet = null;
1244            cloned.values = null;
1245            cloned.modCount = 0;
1246            cloned.size = 0;
1247            cloned.init();
1248            cloned.putAll(this);
1249            return cloned;
1250
1251        } catch (CloneNotSupportedException ex) {
1252            return null;  // should never happen
1253        }
1254    }
1255
1256    /**
1257     * Compares this map with another.
1258     *
1259     * @param obj the object to compare to
1260     * @return true if equal
1261     */
1262    public boolean equals(Object obj) {
1263        if (obj == this) {
1264            return true;
1265        }
1266        if (obj instanceof Map == false) {
1267            return false;
1268        }
1269        Map map = (Map) obj;
1270        if (map.size() != size()) {
1271            return false;
1272        }
1273        MapIterator it = mapIterator();
1274        try {
1275            while (it.hasNext()) {
1276                Object key = it.next();
1277                Object value = it.getValue();
1278                if (value == null) {
1279                    if (map.get(key) != null || map.containsKey(key) == false) {
1280                        return false;
1281                    }
1282                } else {
1283                    if (value.equals(map.get(key)) == false) {
1284                        return false;
1285                    }
1286                }
1287            }
1288        } catch (ClassCastException ignored) {
1289            return false;
1290        } catch (NullPointerException ignored) {
1291            return false;
1292        }
1293        return true;
1294    }
1295
1296    /**
1297     * Gets the standard Map hashCode.
1298     *
1299     * @return the hash code defined in the Map interface
1300     */
1301    public int hashCode() {
1302        int total = 0;
1303        Iterator it = createEntrySetIterator();
1304        while (it.hasNext()) {
1305            total += it.next().hashCode();
1306        }
1307        return total;
1308    }
1309
1310    /**
1311     * Gets the map as a String.
1312     *
1313     * @return a string version of the map
1314     */
1315    public String toString() {
1316        if (size() == 0) {
1317            return "{}";
1318        }
1319        StringBuilder buf = new StringBuilder(32 * size());
1320        buf.append('{');
1321
1322        MapIterator it = mapIterator();
1323        boolean hasNext = it.hasNext();
1324        while (hasNext) {
1325            Object key = it.next();
1326            Object value = it.getValue();
1327            buf.append(key == this ? "(this Map)" : key).append('=').append(value == this ? "(this Map)" : value);
1328
1329            hasNext = it.hasNext();
1330            if (hasNext) {
1331                buf.append(',').append(' ');
1332            }
1333        }
1334
1335        buf.append('}');
1336        return buf.toString();
1337    }
1338}
1339