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