LinkedHashMap.java revision 7ae7ae73754c8b82a2e396098e35553d404c69ef
1/*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.util;
27
28import java.util.function.Consumer;
29import java.util.function.BiConsumer;
30import java.util.function.BiFunction;
31import java.io.IOException;
32
33// Android-added: Note about spliterator order b/33945212 in Android N
34/**
35 * <p>Hash table and linked list implementation of the <tt>Map</tt> interface,
36 * with predictable iteration order.  This implementation differs from
37 * <tt>HashMap</tt> in that it maintains a doubly-linked list running through
38 * all of its entries.  This linked list defines the iteration ordering,
39 * which is normally the order in which keys were inserted into the map
40 * (<i>insertion-order</i>).  Note that insertion order is not affected
41 * if a key is <i>re-inserted</i> into the map.  (A key <tt>k</tt> is
42 * reinserted into a map <tt>m</tt> if <tt>m.put(k, v)</tt> is invoked when
43 * <tt>m.containsKey(k)</tt> would return <tt>true</tt> immediately prior to
44 * the invocation.)
45 *
46 * <p>This implementation spares its clients from the unspecified, generally
47 * chaotic ordering provided by {@link HashMap} (and {@link Hashtable}),
48 * without incurring the increased cost associated with {@link TreeMap}.  It
49 * can be used to produce a copy of a map that has the same order as the
50 * original, regardless of the original map's implementation:
51 * <pre>
52 *     void foo(Map m) {
53 *         Map copy = new LinkedHashMap(m);
54 *         ...
55 *     }
56 * </pre>
57 * This technique is particularly useful if a module takes a map on input,
58 * copies it, and later returns results whose order is determined by that of
59 * the copy.  (Clients generally appreciate having things returned in the same
60 * order they were presented.)
61 *
62 * <p>A special {@link #LinkedHashMap(int,float,boolean) constructor} is
63 * provided to create a linked hash map whose order of iteration is the order
64 * in which its entries were last accessed, from least-recently accessed to
65 * most-recently (<i>access-order</i>).  This kind of map is well-suited to
66 * building LRU caches.  Invoking the {@code put}, {@code putIfAbsent},
67 * {@code get}, {@code getOrDefault}, {@code compute}, {@code computeIfAbsent},
68 * {@code computeIfPresent}, or {@code merge} methods results
69 * in an access to the corresponding entry (assuming it exists after the
70 * invocation completes). The {@code replace} methods only result in an access
71 * of the entry if the value is replaced.  The {@code putAll} method generates one
72 * entry access for each mapping in the specified map, in the order that
73 * key-value mappings are provided by the specified map's entry set iterator.
74 * <i>No other methods generate entry accesses.</i>  In particular, operations
75 * on collection-views do <i>not</i> affect the order of iteration of the
76 * backing map.
77 *
78 * <p>The {@link #removeEldestEntry(Map.Entry)} method may be overridden to
79 * impose a policy for removing stale mappings automatically when new mappings
80 * are added to the map.
81 *
82 * <p>This class provides all of the optional <tt>Map</tt> operations, and
83 * permits null elements.  Like <tt>HashMap</tt>, it provides constant-time
84 * performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
85 * <tt>remove</tt>), assuming the hash function disperses elements
86 * properly among the buckets.  Performance is likely to be just slightly
87 * below that of <tt>HashMap</tt>, due to the added expense of maintaining the
88 * linked list, with one exception: Iteration over the collection-views
89 * of a <tt>LinkedHashMap</tt> requires time proportional to the <i>size</i>
90 * of the map, regardless of its capacity.  Iteration over a <tt>HashMap</tt>
91 * is likely to be more expensive, requiring time proportional to its
92 * <i>capacity</i>.
93 *
94 * <p>A linked hash map has two parameters that affect its performance:
95 * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
96 * as for <tt>HashMap</tt>.  Note, however, that the penalty for choosing an
97 * excessively high value for initial capacity is less severe for this class
98 * than for <tt>HashMap</tt>, as iteration times for this class are unaffected
99 * by capacity.
100 *
101 * <p><strong>Note that this implementation is not synchronized.</strong>
102 * If multiple threads access a linked hash map concurrently, and at least
103 * one of the threads modifies the map structurally, it <em>must</em> be
104 * synchronized externally.  This is typically accomplished by
105 * synchronizing on some object that naturally encapsulates the map.
106 *
107 * If no such object exists, the map should be "wrapped" using the
108 * {@link Collections#synchronizedMap Collections.synchronizedMap}
109 * method.  This is best done at creation time, to prevent accidental
110 * unsynchronized access to the map:<pre>
111 *   Map m = Collections.synchronizedMap(new LinkedHashMap(...));</pre>
112 *
113 * A structural modification is any operation that adds or deletes one or more
114 * mappings or, in the case of access-ordered linked hash maps, affects
115 * iteration order.  In insertion-ordered linked hash maps, merely changing
116 * the value associated with a key that is already contained in the map is not
117 * a structural modification.  <strong>In access-ordered linked hash maps,
118 * merely querying the map with <tt>get</tt> is a structural modification.
119 * </strong>)
120 *
121 * <p>The iterators returned by the <tt>iterator</tt> method of the collections
122 * returned by all of this class's collection view methods are
123 * <em>fail-fast</em>: if the map is structurally modified at any time after
124 * the iterator is created, in any way except through the iterator's own
125 * <tt>remove</tt> method, the iterator will throw a {@link
126 * ConcurrentModificationException}.  Thus, in the face of concurrent
127 * modification, the iterator fails quickly and cleanly, rather than risking
128 * arbitrary, non-deterministic behavior at an undetermined time in the future.
129 *
130 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
131 * as it is, generally speaking, impossible to make any hard guarantees in the
132 * presence of unsynchronized concurrent modification.  Fail-fast iterators
133 * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
134 * Therefore, it would be wrong to write a program that depended on this
135 * exception for its correctness:   <i>the fail-fast behavior of iterators
136 * should be used only to detect bugs.</i>
137 *
138 * <p>The spliterators returned by the spliterator method of the collections
139 * returned by all of this class's collection view methods are
140 * <em><a href="Spliterator.html#binding">late-binding</a></em>,
141 * <em>fail-fast</em>, and additionally report {@link Spliterator#ORDERED}.
142 * <em>Note</em>: The implementation of these spliterators in Android Nougat
143 * (API levels 24 and 25) uses the wrong order (inconsistent with the
144 * iterators, which use the correct order), despite reporting
145 * {@link Spliterator#ORDERED}. You may use the following code fragments
146 * to obtain a correctly ordered Spliterator on API level 24 and 25:
147 * <ul>
148 *     <li>For a Collection view {@code c = lhm.keySet()},
149 *         {@code c = lhm.keySet()} or {@code c = lhm.values()}, use
150 *         {@code java.util.Spliterators.spliterator(c, c.spliterator().characteristics())}
151 *         instead of {@code c.spliterator()}.
152 *     <li>Instead of {@code lhm.stream()} or {@code lhm.parallelStream()}, use
153 *         {@code java.util.stream.StreamSupport.stream(spliterator, false)}
154 *         to construct a (nonparallel) {@link java.util.stream.Stream} from
155 *         such a {@code Spliterator}.
156 * </ul>
157 * Note that these workarounds are only suggested where {@code lhm} is a
158 * {@code LinkedHashMap}.
159 *
160 * <p>This class is a member of the
161 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
162 * Java Collections Framework</a>.
163 *
164 * @implNote
165 * The spliterators returned by the spliterator method of the collections
166 * returned by all of this class's collection view methods are created from
167 * the iterators of the corresponding collections.
168 *
169 * @param <K> the type of keys maintained by this map
170 * @param <V> the type of mapped values
171 *
172 * @author  Josh Bloch
173 * @see     Object#hashCode()
174 * @see     Collection
175 * @see     Map
176 * @see     HashMap
177 * @see     TreeMap
178 * @see     Hashtable
179 * @since   1.4
180 */
181public class LinkedHashMap<K,V>
182    extends HashMap<K,V>
183    implements Map<K,V>
184{
185
186    /*
187     * Implementation note.  A previous version of this class was
188     * internally structured a little differently. Because superclass
189     * HashMap now uses trees for some of its nodes, class
190     * LinkedHashMap.Entry is now treated as intermediary node class
191     * that can also be converted to tree form.
192     *
193     * Android-changed BEGIN
194     * LinkedHashMapEntry should not be renamed. Specifically, for
195     * source compatibility with earlier versions of Android, this
196     * nested class must not be named "Entry". Otherwise, it would
197     * hide Map.Entry which would break compilation of code like:
198     *
199     * LinkedHashMap.Entry<K, V> entry = map.entrySet().iterator.next()
200     *
201     * To compile, that code snippet's "LinkedHashMap.Entry" must
202     * mean java.util.Map.Entry which is the compile time type of
203     * entrySet()'s elements.
204     * Android-changed END
205     *
206     * The changes in node classes also require using two fields
207     * (head, tail) rather than a pointer to a header node to maintain
208     * the doubly-linked before/after list. This class also
209     * previously used a different style of callback methods upon
210     * access, insertion, and removal.
211     */
212
213    /**
214     * HashMap.Node subclass for normal LinkedHashMap entries.
215     */
216    static class LinkedHashMapEntry<K,V> extends HashMap.Node<K,V> {
217        LinkedHashMapEntry<K,V> before, after;
218        LinkedHashMapEntry(int hash, K key, V value, Node<K,V> next) {
219            super(hash, key, value, next);
220        }
221    }
222
223    private static final long serialVersionUID = 3801124242820219131L;
224
225    /**
226     * The head (eldest) of the doubly linked list.
227     */
228    transient LinkedHashMapEntry<K,V> head;
229
230    /**
231     * The tail (youngest) of the doubly linked list.
232     */
233    transient LinkedHashMapEntry<K,V> tail;
234
235    /**
236     * The iteration ordering method for this linked hash map: <tt>true</tt>
237     * for access-order, <tt>false</tt> for insertion-order.
238     *
239     * @serial
240     */
241    final boolean accessOrder;
242
243    // internal utilities
244
245    // link at the end of list
246    private void linkNodeLast(LinkedHashMapEntry<K,V> p) {
247        LinkedHashMapEntry<K,V> last = tail;
248        tail = p;
249        if (last == null)
250            head = p;
251        else {
252            p.before = last;
253            last.after = p;
254        }
255    }
256
257    // apply src's links to dst
258    private void transferLinks(LinkedHashMapEntry<K,V> src,
259                               LinkedHashMapEntry<K,V> dst) {
260        LinkedHashMapEntry<K,V> b = dst.before = src.before;
261        LinkedHashMapEntry<K,V> a = dst.after = src.after;
262        if (b == null)
263            head = dst;
264        else
265            b.after = dst;
266        if (a == null)
267            tail = dst;
268        else
269            a.before = dst;
270    }
271
272    // overrides of HashMap hook methods
273
274    void reinitialize() {
275        super.reinitialize();
276        head = tail = null;
277    }
278
279    Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
280        LinkedHashMapEntry<K,V> p =
281            new LinkedHashMapEntry<K,V>(hash, key, value, e);
282        linkNodeLast(p);
283        return p;
284    }
285
286    Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
287        LinkedHashMapEntry<K,V> q = (LinkedHashMapEntry<K,V>)p;
288        LinkedHashMapEntry<K,V> t =
289            new LinkedHashMapEntry<K,V>(q.hash, q.key, q.value, next);
290        transferLinks(q, t);
291        return t;
292    }
293
294    TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
295        TreeNode<K,V> p = new TreeNode<K,V>(hash, key, value, next);
296        linkNodeLast(p);
297        return p;
298    }
299
300    TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
301        LinkedHashMapEntry<K,V> q = (LinkedHashMapEntry<K,V>)p;
302        TreeNode<K,V> t = new TreeNode<K,V>(q.hash, q.key, q.value, next);
303        transferLinks(q, t);
304        return t;
305    }
306
307    void afterNodeRemoval(Node<K,V> e) { // unlink
308        LinkedHashMapEntry<K,V> p =
309            (LinkedHashMapEntry<K,V>)e, b = p.before, a = p.after;
310        p.before = p.after = null;
311        if (b == null)
312            head = a;
313        else
314            b.after = a;
315        if (a == null)
316            tail = b;
317        else
318            a.before = b;
319    }
320
321    void afterNodeInsertion(boolean evict) { // possibly remove eldest
322        LinkedHashMapEntry<K,V> first;
323        if (evict && (first = head) != null && removeEldestEntry(first)) {
324            K key = first.key;
325            removeNode(hash(key), key, null, false, true);
326        }
327    }
328
329    void afterNodeAccess(Node<K,V> e) { // move node to last
330        LinkedHashMapEntry<K,V> last;
331        if (accessOrder && (last = tail) != e) {
332            LinkedHashMapEntry<K,V> p =
333                (LinkedHashMapEntry<K,V>)e, b = p.before, a = p.after;
334            p.after = null;
335            if (b == null)
336                head = a;
337            else
338                b.after = a;
339            if (a != null)
340                a.before = b;
341            else
342                last = b;
343            if (last == null)
344                head = p;
345            else {
346                p.before = last;
347                last.after = p;
348            }
349            tail = p;
350            ++modCount;
351        }
352    }
353
354    void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
355        for (LinkedHashMapEntry<K,V> e = head; e != null; e = e.after) {
356            s.writeObject(e.key);
357            s.writeObject(e.value);
358        }
359    }
360
361    /**
362     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
363     * with the specified initial capacity and load factor.
364     *
365     * @param  initialCapacity the initial capacity
366     * @param  loadFactor      the load factor
367     * @throws IllegalArgumentException if the initial capacity is negative
368     *         or the load factor is nonpositive
369     */
370    public LinkedHashMap(int initialCapacity, float loadFactor) {
371        super(initialCapacity, loadFactor);
372        accessOrder = false;
373    }
374
375    /**
376     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
377     * with the specified initial capacity and a default load factor (0.75).
378     *
379     * @param  initialCapacity the initial capacity
380     * @throws IllegalArgumentException if the initial capacity is negative
381     */
382    public LinkedHashMap(int initialCapacity) {
383        super(initialCapacity);
384        accessOrder = false;
385    }
386
387    /**
388     * Constructs an empty insertion-ordered <tt>LinkedHashMap</tt> instance
389     * with the default initial capacity (16) and load factor (0.75).
390     */
391    public LinkedHashMap() {
392        super();
393        accessOrder = false;
394    }
395
396    /**
397     * Constructs an insertion-ordered <tt>LinkedHashMap</tt> instance with
398     * the same mappings as the specified map.  The <tt>LinkedHashMap</tt>
399     * instance is created with a default load factor (0.75) and an initial
400     * capacity sufficient to hold the mappings in the specified map.
401     *
402     * @param  m the map whose mappings are to be placed in this map
403     * @throws NullPointerException if the specified map is null
404     */
405    public LinkedHashMap(Map<? extends K, ? extends V> m) {
406        super();
407        accessOrder = false;
408        putMapEntries(m, false);
409    }
410
411    /**
412     * Constructs an empty <tt>LinkedHashMap</tt> instance with the
413     * specified initial capacity, load factor and ordering mode.
414     *
415     * @param  initialCapacity the initial capacity
416     * @param  loadFactor      the load factor
417     * @param  accessOrder     the ordering mode - <tt>true</tt> for
418     *         access-order, <tt>false</tt> for insertion-order
419     * @throws IllegalArgumentException if the initial capacity is negative
420     *         or the load factor is nonpositive
421     */
422    public LinkedHashMap(int initialCapacity,
423                         float loadFactor,
424                         boolean accessOrder) {
425        super(initialCapacity, loadFactor);
426        this.accessOrder = accessOrder;
427    }
428
429
430    /**
431     * Returns <tt>true</tt> if this map maps one or more keys to the
432     * specified value.
433     *
434     * @param value value whose presence in this map is to be tested
435     * @return <tt>true</tt> if this map maps one or more keys to the
436     *         specified value
437     */
438    public boolean containsValue(Object value) {
439        for (LinkedHashMapEntry<K,V> e = head; e != null; e = e.after) {
440            V v = e.value;
441            if (v == value || (value != null && value.equals(v)))
442                return true;
443        }
444        return false;
445    }
446
447    /**
448     * Returns the value to which the specified key is mapped,
449     * or {@code null} if this map contains no mapping for the key.
450     *
451     * <p>More formally, if this map contains a mapping from a key
452     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
453     * key.equals(k))}, then this method returns {@code v}; otherwise
454     * it returns {@code null}.  (There can be at most one such mapping.)
455     *
456     * <p>A return value of {@code null} does not <i>necessarily</i>
457     * indicate that the map contains no mapping for the key; it's also
458     * possible that the map explicitly maps the key to {@code null}.
459     * The {@link #containsKey containsKey} operation may be used to
460     * distinguish these two cases.
461     */
462    public V get(Object key) {
463        Node<K,V> e;
464        if ((e = getNode(hash(key), key)) == null)
465            return null;
466        if (accessOrder)
467            afterNodeAccess(e);
468        return e.value;
469    }
470
471    /**
472     * {@inheritDoc}
473     */
474    public V getOrDefault(Object key, V defaultValue) {
475       Node<K,V> e;
476       if ((e = getNode(hash(key), key)) == null)
477           return defaultValue;
478       if (accessOrder)
479           afterNodeAccess(e);
480       return e.value;
481   }
482
483    /**
484     * {@inheritDoc}
485     */
486    public void clear() {
487        super.clear();
488        head = tail = null;
489    }
490
491    /**
492     * Returns the eldest entry in the map, or {@code null} if the map is empty.
493     *
494     * Android-added.
495     *
496     * @hide
497     */
498    public Map.Entry<K, V> eldest() {
499        return head;
500    }
501
502    /**
503     * Returns <tt>true</tt> if this map should remove its eldest entry.
504     * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
505     * inserting a new entry into the map.  It provides the implementor
506     * with the opportunity to remove the eldest entry each time a new one
507     * is added.  This is useful if the map represents a cache: it allows
508     * the map to reduce memory consumption by deleting stale entries.
509     *
510     * <p>Sample use: this override will allow the map to grow up to 100
511     * entries and then delete the eldest entry each time a new entry is
512     * added, maintaining a steady state of 100 entries.
513     * <pre>
514     *     private static final int MAX_ENTRIES = 100;
515     *
516     *     protected boolean removeEldestEntry(Map.Entry eldest) {
517     *        return size() &gt; MAX_ENTRIES;
518     *     }
519     * </pre>
520     *
521     * <p>This method typically does not modify the map in any way,
522     * instead allowing the map to modify itself as directed by its
523     * return value.  It <i>is</i> permitted for this method to modify
524     * the map directly, but if it does so, it <i>must</i> return
525     * <tt>false</tt> (indicating that the map should not attempt any
526     * further modification).  The effects of returning <tt>true</tt>
527     * after modifying the map from within this method are unspecified.
528     *
529     * <p>This implementation merely returns <tt>false</tt> (so that this
530     * map acts like a normal map - the eldest element is never removed).
531     *
532     * @param    eldest The least recently inserted entry in the map, or if
533     *           this is an access-ordered map, the least recently accessed
534     *           entry.  This is the entry that will be removed it this
535     *           method returns <tt>true</tt>.  If the map was empty prior
536     *           to the <tt>put</tt> or <tt>putAll</tt> invocation resulting
537     *           in this invocation, this will be the entry that was just
538     *           inserted; in other words, if the map contains a single
539     *           entry, the eldest entry is also the newest.
540     * @return   <tt>true</tt> if the eldest entry should be removed
541     *           from the map; <tt>false</tt> if it should be retained.
542     */
543    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
544        return false;
545    }
546
547    /**
548     * Returns a {@link Set} view of the keys contained in this map.
549     * The set is backed by the map, so changes to the map are
550     * reflected in the set, and vice-versa.  If the map is modified
551     * while an iteration over the set is in progress (except through
552     * the iterator's own <tt>remove</tt> operation), the results of
553     * the iteration are undefined.  The set supports element removal,
554     * which removes the corresponding mapping from the map, via the
555     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
556     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
557     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
558     * operations.
559     * Its {@link Spliterator} typically provides faster sequential
560     * performance but much poorer parallel performance than that of
561     * {@code HashMap}.
562     *
563     * @return a set view of the keys contained in this map
564     */
565    public Set<K> keySet() {
566        Set<K> ks;
567        return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks;
568    }
569
570    final class LinkedKeySet extends AbstractSet<K> {
571        public final int size()                 { return size; }
572        public final void clear()               { LinkedHashMap.this.clear(); }
573        public final Iterator<K> iterator() {
574            return new LinkedKeyIterator();
575        }
576        public final boolean contains(Object o) { return containsKey(o); }
577        public final boolean remove(Object key) {
578            return removeNode(hash(key), key, null, false, true) != null;
579        }
580        public final Spliterator<K> spliterator()  {
581            return Spliterators.spliterator(this, Spliterator.SIZED |
582                                            Spliterator.ORDERED |
583                                            Spliterator.DISTINCT);
584        }
585        public final void forEach(Consumer<? super K> action) {
586            if (action == null)
587                throw new NullPointerException();
588            int mc = modCount;
589            // Android-changed: Detect changes to modCount early.
590            for (LinkedHashMapEntry<K,V> e = head; (e != null && modCount == mc); e = e.after)
591                action.accept(e.key);
592            if (modCount != mc)
593                throw new ConcurrentModificationException();
594        }
595    }
596
597    /**
598     * Returns a {@link Collection} view of the values contained in this map.
599     * The collection is backed by the map, so changes to the map are
600     * reflected in the collection, and vice-versa.  If the map is
601     * modified while an iteration over the collection is in progress
602     * (except through the iterator's own <tt>remove</tt> operation),
603     * the results of the iteration are undefined.  The collection
604     * supports element removal, which removes the corresponding
605     * mapping from the map, via the <tt>Iterator.remove</tt>,
606     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
607     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
608     * support the <tt>add</tt> or <tt>addAll</tt> operations.
609     * Its {@link Spliterator} typically provides faster sequential
610     * performance but much poorer parallel performance than that of
611     * {@code HashMap}.
612     *
613     * @return a view of the values contained in this map
614     */
615    public Collection<V> values() {
616        Collection<V> vs;
617        return (vs = values) == null ? (values = new LinkedValues()) : vs;
618    }
619
620    final class LinkedValues extends AbstractCollection<V> {
621        public final int size()                 { return size; }
622        public final void clear()               { LinkedHashMap.this.clear(); }
623        public final Iterator<V> iterator() {
624            return new LinkedValueIterator();
625        }
626        public final boolean contains(Object o) { return containsValue(o); }
627        public final Spliterator<V> spliterator() {
628            return Spliterators.spliterator(this, Spliterator.SIZED |
629                                            Spliterator.ORDERED);
630        }
631        public final void forEach(Consumer<? super V> action) {
632            if (action == null)
633                throw new NullPointerException();
634            int mc = modCount;
635            // Android-changed: Detect changes to modCount early.
636            for (LinkedHashMapEntry<K,V> e = head; (e != null && modCount == mc); e = e.after)
637                action.accept(e.value);
638            if (modCount != mc)
639                throw new ConcurrentModificationException();
640        }
641    }
642
643    /**
644     * Returns a {@link Set} view of the mappings contained in this map.
645     * The set is backed by the map, so changes to the map are
646     * reflected in the set, and vice-versa.  If the map is modified
647     * while an iteration over the set is in progress (except through
648     * the iterator's own <tt>remove</tt> operation, or through the
649     * <tt>setValue</tt> operation on a map entry returned by the
650     * iterator) the results of the iteration are undefined.  The set
651     * supports element removal, which removes the corresponding
652     * mapping from the map, via the <tt>Iterator.remove</tt>,
653     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
654     * <tt>clear</tt> operations.  It does not support the
655     * <tt>add</tt> or <tt>addAll</tt> operations.
656     * Its {@link Spliterator} typically provides faster sequential
657     * performance but much poorer parallel performance than that of
658     * {@code HashMap}.
659     *
660     * @return a set view of the mappings contained in this map
661     */
662    public Set<Map.Entry<K,V>> entrySet() {
663        Set<Map.Entry<K,V>> es;
664        return (es = entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
665    }
666
667    final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
668        public final int size()                 { return size; }
669        public final void clear()               { LinkedHashMap.this.clear(); }
670        public final Iterator<Map.Entry<K,V>> iterator() {
671            return new LinkedEntryIterator();
672        }
673        public final boolean contains(Object o) {
674            if (!(o instanceof Map.Entry))
675                return false;
676            Map.Entry<?,?> e = (Map.Entry<?,?>) o;
677            Object key = e.getKey();
678            Node<K,V> candidate = getNode(hash(key), key);
679            return candidate != null && candidate.equals(e);
680        }
681        public final boolean remove(Object o) {
682            if (o instanceof Map.Entry) {
683                Map.Entry<?,?> e = (Map.Entry<?,?>) o;
684                Object key = e.getKey();
685                Object value = e.getValue();
686                return removeNode(hash(key), key, value, true, true) != null;
687            }
688            return false;
689        }
690        public final Spliterator<Map.Entry<K,V>> spliterator() {
691            return Spliterators.spliterator(this, Spliterator.SIZED |
692                                            Spliterator.ORDERED |
693                                            Spliterator.DISTINCT);
694        }
695        public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
696            if (action == null)
697                throw new NullPointerException();
698            int mc = modCount;
699            // Android-changed: Detect changes to modCount early.
700            for (LinkedHashMapEntry<K,V> e = head; (e != null && mc == modCount); e = e.after)
701                action.accept(e);
702            if (modCount != mc)
703                throw new ConcurrentModificationException();
704        }
705    }
706
707    // Map overrides
708
709    public void forEach(BiConsumer<? super K, ? super V> action) {
710        if (action == null)
711            throw new NullPointerException();
712        int mc = modCount;
713        // Android-changed: Detect changes to modCount early.
714        for (LinkedHashMapEntry<K,V> e = head; modCount == mc && e != null; e = e.after)
715            action.accept(e.key, e.value);
716        if (modCount != mc)
717            throw new ConcurrentModificationException();
718    }
719
720    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
721        if (function == null)
722            throw new NullPointerException();
723        int mc = modCount;
724        // Android-changed: Detect changes to modCount early.
725        for (LinkedHashMapEntry<K,V> e = head; modCount == mc && e != null; e = e.after)
726            e.value = function.apply(e.key, e.value);
727        if (modCount != mc)
728            throw new ConcurrentModificationException();
729    }
730
731    // Iterators
732
733    abstract class LinkedHashIterator {
734        LinkedHashMapEntry<K,V> next;
735        LinkedHashMapEntry<K,V> current;
736        int expectedModCount;
737
738        LinkedHashIterator() {
739            next = head;
740            expectedModCount = modCount;
741            current = null;
742        }
743
744        public final boolean hasNext() {
745            return next != null;
746        }
747
748        final LinkedHashMapEntry<K,V> nextNode() {
749            LinkedHashMapEntry<K,V> e = next;
750            if (modCount != expectedModCount)
751                throw new ConcurrentModificationException();
752            if (e == null)
753                throw new NoSuchElementException();
754            current = e;
755            next = e.after;
756            return e;
757        }
758
759        public final void remove() {
760            Node<K,V> p = current;
761            if (p == null)
762                throw new IllegalStateException();
763            if (modCount != expectedModCount)
764                throw new ConcurrentModificationException();
765            current = null;
766            K key = p.key;
767            removeNode(hash(key), key, null, false, false);
768            expectedModCount = modCount;
769        }
770    }
771
772    final class LinkedKeyIterator extends LinkedHashIterator
773        implements Iterator<K> {
774        public final K next() { return nextNode().getKey(); }
775    }
776
777    final class LinkedValueIterator extends LinkedHashIterator
778        implements Iterator<V> {
779        public final V next() { return nextNode().value; }
780    }
781
782    final class LinkedEntryIterator extends LinkedHashIterator
783        implements Iterator<Map.Entry<K,V>> {
784        public final Map.Entry<K,V> next() { return nextNode(); }
785    }
786
787
788}
789