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