001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4.map;
018
019import java.io.IOException;
020import java.io.ObjectInputStream;
021import java.io.ObjectOutputStream;
022import java.util.AbstractCollection;
023import java.util.AbstractMap;
024import java.util.AbstractSet;
025import java.util.Arrays;
026import java.util.Collection;
027import java.util.ConcurrentModificationException;
028import java.util.Iterator;
029import java.util.Map;
030import java.util.NoSuchElementException;
031import java.util.Set;
032
033import org.apache.commons.collections4.CollectionUtils;
034import org.apache.commons.collections4.IterableMap;
035import org.apache.commons.collections4.KeyValue;
036import org.apache.commons.collections4.MapIterator;
037import org.apache.commons.collections4.iterators.EmptyIterator;
038import org.apache.commons.collections4.iterators.EmptyMapIterator;
039
040/**
041 * An abstract implementation of a hash-based map which provides numerous points for
042 * subclasses to override.
043 * <p>
044 * This class implements all the features necessary for a subclass hash-based map.
045 * Key-value entries are stored in instances of the {@code HashEntry} class,
046 * which can be overridden and replaced. The iterators can similarly be replaced,
047 * without the need to replace the KeySet, EntrySet and Values view classes.
048 * <p>
049 * Overridable methods are provided to change the default hashing behavior, and
050 * to change how entries are added to and removed from the map. Hopefully, all you
051 * need for unusual subclasses is here.
052 * <p>
053 * NOTE: From Commons Collections 3.1 this class extends AbstractMap.
054 * This is to provide backwards compatibility for ReferenceMap between v3.0 and v3.1.
055 * This extends clause will be removed in v5.0.
056 *
057 * @param <K> the type of the keys in this map
058 * @param <V> the type of the values in this map
059 * @since 3.0
060 */
061public class AbstractHashedMap<K, V> extends AbstractMap<K, V> implements IterableMap<K, V> {
062
063    /**
064     * EntrySet implementation.
065     *
066     * @param <K> the type of the keys in the map
067     * @param <V> the type of the values in the map
068     */
069    protected static class EntrySet<K, V> extends AbstractSet<Map.Entry<K, V>> {
070        /** The parent map */
071        private final AbstractHashedMap<K, V> parent;
072
073        protected EntrySet(final AbstractHashedMap<K, V> parent) {
074            this.parent = parent;
075        }
076
077        @Override
078        public void clear() {
079            parent.clear();
080        }
081
082        @Override
083        public boolean contains(final Object entry) {
084            if (entry instanceof Map.Entry) {
085                final Map.Entry<?, ?> e = (Map.Entry<?, ?>) entry;
086                final Entry<K, V> match = parent.getEntry(e.getKey());
087                return match != null && match.equals(e);
088            }
089            return false;
090        }
091
092        @Override
093        public Iterator<Map.Entry<K, V>> iterator() {
094            return parent.createEntrySetIterator();
095        }
096
097        @Override
098        public boolean remove(final Object obj) {
099            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}