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.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/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;
 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
 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
 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 
 250     void reinitialize() {
 251         super.reinitialize();
 252         head = tail = null;
 253     }
 254 
 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 
 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 
 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 
 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 
 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 
 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 
 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 
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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      */
 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> {
 540         public final int size()                 { return size; }
 541         public final void clear()               { LinkedHashMap.this.clear(); }
 542         public final Iterator<K> iterator() {
 543             return new LinkedKeyIterator();
 544         }
 545         public final boolean contains(Object o) { return containsKey(o); }
 546         public final boolean remove(Object key) {
 547             return removeNode(hash(key), key, null, false, true) != null;
 548         }
 549         public final Spliterator<K> spliterator()  {
 550             return Spliterators.spliterator(this, Spliterator.SIZED |
 551                                             Spliterator.ORDERED |
 552                                             Spliterator.DISTINCT);
 553         }
 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      */
 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> {
 593         public final int size()                 { return size; }
 594         public final void clear()               { LinkedHashMap.this.clear(); }
 595         public final Iterator<V> iterator() {
 596             return new LinkedValueIterator();
 597         }
 598         public final boolean contains(Object o) { return containsValue(o); }
 599         public final Spliterator<V> spliterator() {
 600             return Spliterators.spliterator(this, Spliterator.SIZED |
 601                                             Spliterator.ORDERED);
 602         }
 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      */
 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>> {
 639         public final int size()                 { return size; }
 640         public final void clear()               { LinkedHashMap.this.clear(); }
 641         public final Iterator<Map.Entry<K,V>> iterator() {
 642             return new LinkedEntryIterator();
 643         }
 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         }
 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         }
 661         public final Spliterator<Map.Entry<K,V>> spliterator() {
 662             return Spliterators.spliterator(this, Spliterator.SIZED |
 663                                             Spliterator.ORDERED |
 664                                             Spliterator.DISTINCT);
 665         }
 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 
 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 
 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 
 706         LinkedHashIterator() {
 707             next = head;
 708             expectedModCount = modCount;
 709             current = null;
 710         }
 711 
 712         public final boolean hasNext() {
 713             return next != null;
 714         }
 715 
 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 
 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> {
 741         public final K next() { return nextNode().getKey(); }
 742     }
 743 
 744     final class LinkedValueIterator extends LinkedHashIterator
 745         implements Iterator<V> {
 746         public final V next() { return nextNode().value; }
 747     }
 748 
 749     final class LinkedEntryIterator extends LinkedHashIterator
 750         implements Iterator<Map.Entry<K,V>> {
 751         public final Map.Entry<K,V> next() { return nextNode(); }
 752     }
 753 
 754 
 755 }