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