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