1 /*
2  * Copyright (c) 1997, 2023, 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 import java.util.function.Function;
33 
34 // Android-added: Note about spliterator order b/33945212 in Android N
35 /**
36  * <p>Hash table and linked list implementation of the {@code Map} interface,
37  * with well-defined encounter order.  This implementation differs from
38  * {@code HashMap} in that it maintains a doubly-linked list running through all of
39  * its entries.  This linked list defines the encounter order (the order of iteration),
40  * which is normally the order in which keys were inserted into the map
41  * (<i>insertion-order</i>). The least recently inserted entry (the eldest) is
42  * first, and the youngest entry is last. Note that encounter order is not affected
43  * if a key is <i>re-inserted</i> into the map with the {@code put} method. (A key
44  * {@code k} is reinserted into a map {@code m} if {@code m.put(k, v)} is invoked when
45  * {@code m.containsKey(k)} would return {@code true} immediately prior to
46  * the invocation.) The reverse-ordered view of this map is in the opposite order, with
47  * the youngest entry appearing first and the eldest entry appearing last.
48  * The encounter order of entries already in the map can be changed by using
49  * the {@link #putFirst putFirst} and {@link #putLast putLast} methods.
50  *
51  * <p>This implementation spares its clients from the unspecified, generally
52  * chaotic ordering provided by {@link HashMap} (and {@link Hashtable}),
53  * without incurring the increased cost associated with {@link TreeMap}.  It
54  * can be used to produce a copy of a map that has the same order as the
55  * original, regardless of the original map's implementation:
56  * <pre>{@code
57  *     void foo(Map<String, Integer> m) {
58  *         Map<String, Integer> copy = new LinkedHashMap<>(m);
59  *         ...
60  *     }
61  * }</pre>
62  * This technique is particularly useful if a module takes a map on input,
63  * copies it, and later returns results whose order is determined by that of
64  * the copy.  (Clients generally appreciate having things returned in the same
65  * order they were presented.)
66  *
67  * <p>A special {@link #LinkedHashMap(int,float,boolean) constructor} is
68  * provided to create a linked hash map whose encounter order is the order
69  * in which its entries were last accessed, from least-recently accessed to
70  * most-recently (<i>access-order</i>).  This kind of map is well-suited to
71  * building LRU caches.  Invoking the {@code put}, {@code putIfAbsent},
72  * {@code get}, {@code getOrDefault}, {@code compute}, {@code computeIfAbsent},
73  * {@code computeIfPresent}, or {@code merge} methods results
74  * in an access to the corresponding entry (assuming it exists after the
75  * invocation completes). The {@code replace} methods only result in an access
76  * of the entry if the value is replaced.  The {@code putAll} method generates one
77  * entry access for each mapping in the specified map, in the order that
78  * key-value mappings are provided by the specified map's entry set iterator.
79  * <i>No other methods generate entry accesses.</i> Invoking these methods on the
80  * reversed view generates accesses to entries on the backing map. Note that in the
81  * reversed view, an access to an entry moves it first in encounter order.
82  * Explicit-positioning methods such as {@code putFirst} or {@code lastEntry}, whether on
83  * the map or on its reverse-ordered view, perform the positioning operation and
84  * do not generate entry accesses. Operations on the {@code keySet}, {@code values},
85  * and {@code entrySet} views or on their sequenced counterparts do <i>not</i> affect
86  * the encounter order of the backing map.
87  *
88  * <p>The {@link #removeEldestEntry(Map.Entry)} method may be overridden to
89  * impose a policy for removing stale mappings automatically when new mappings
90  * are added to the map. Alternatively, since the "eldest" entry is the first
91  * entry in encounter order, programs can inspect and remove stale mappings through
92  * use of the {@link #firstEntry firstEntry} and {@link #pollFirstEntry pollFirstEntry}
93  * methods.
94  *
95  * <p>This class provides all of the optional {@code Map} and {@code SequencedMap} operations,
96  * and it permits null elements.  Like {@code HashMap}, it provides constant-time
97  * performance for the basic operations ({@code add}, {@code contains} and
98  * {@code remove}), assuming the hash function disperses elements
99  * properly among the buckets.  Performance is likely to be just slightly
100  * below that of {@code HashMap}, due to the added expense of maintaining the
101  * linked list, with one exception: Iteration over the collection-views
102  * of a {@code LinkedHashMap} requires time proportional to the <i>size</i>
103  * of the map, regardless of its capacity.  Iteration over a {@code HashMap}
104  * is likely to be more expensive, requiring time proportional to its
105  * <i>capacity</i>.
106  *
107  * <p>A linked hash map has two parameters that affect its performance:
108  * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
109  * as for {@code HashMap}.  Note, however, that the penalty for choosing an
110  * excessively high value for initial capacity is less severe for this class
111  * than for {@code HashMap}, as iteration times for this class are unaffected
112  * by capacity.
113  *
114  * <p><strong>Note that this implementation is not synchronized.</strong>
115  * If multiple threads access a linked hash map concurrently, and at least
116  * one of the threads modifies the map structurally, it <em>must</em> be
117  * synchronized externally.  This is typically accomplished by
118  * synchronizing on some object that naturally encapsulates the map.
119  *
120  * If no such object exists, the map should be "wrapped" using the
121  * {@link Collections#synchronizedMap Collections.synchronizedMap}
122  * method.  This is best done at creation time, to prevent accidental
123  * unsynchronized access to the map:<pre>
124  *   Map m = Collections.synchronizedMap(new LinkedHashMap(...));</pre>
125  *
126  * A structural modification is any operation that adds or deletes one or more
127  * mappings or, in the case of access-ordered linked hash maps, affects
128  * iteration order.  In insertion-ordered linked hash maps, merely changing
129  * the value associated with a key that is already contained in the map is not
130  * a structural modification.  <strong>In access-ordered linked hash maps,
131  * merely querying the map with {@code get} is a structural modification.
132  * </strong>)
133  *
134  * <p>The iterators returned by the {@code iterator} method of the collections
135  * returned by all of this class's collection view methods are
136  * <em>fail-fast</em>: if the map is structurally modified at any time after
137  * the iterator is created, in any way except through the iterator's own
138  * {@code remove} method, the iterator will throw a {@link
139  * ConcurrentModificationException}.  Thus, in the face of concurrent
140  * modification, the iterator fails quickly and cleanly, rather than risking
141  * arbitrary, non-deterministic behavior at an undetermined time in the future.
142  *
143  * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
144  * as it is, generally speaking, impossible to make any hard guarantees in the
145  * presence of unsynchronized concurrent modification.  Fail-fast iterators
146  * throw {@code ConcurrentModificationException} on a best-effort basis.
147  * Therefore, it would be wrong to write a program that depended on this
148  * exception for its correctness:   <i>the fail-fast behavior of iterators
149  * should be used only to detect bugs.</i>
150  *
151  * <p>The spliterators returned by the spliterator method of the collections
152  * returned by all of this class's collection view methods are
153  * <em><a href="Spliterator.html#binding">late-binding</a></em>,
154  * <em>fail-fast</em>, and additionally report {@link Spliterator#ORDERED}.
155  * <em>Note</em>: The implementation of these spliterators in Android Nougat
156  * (API levels 24 and 25) uses the wrong order (inconsistent with the
157  * iterators, which use the correct order), despite reporting
158  * {@link Spliterator#ORDERED}. You may use the following code fragments
159  * to obtain a correctly ordered Spliterator on API level 24 and 25:
160  * <ul>
161  *     <li>For a Collection view {@code c = lhm.keySet()},
162  *         {@code c = lhm.entrySet()} or {@code c = lhm.values()}, use
163  *         {@code java.util.Spliterators.spliterator(c, c.spliterator().characteristics())}
164  *         instead of {@code c.spliterator()}.
165  *     <li>Instead of {@code c.stream()} or {@code c.parallelStream()}, use
166  *         {@code java.util.stream.StreamSupport.stream(spliterator, false)}
167  *         to construct a (nonparallel) {@link java.util.stream.Stream} from
168  *         such a {@code Spliterator}.
169  * </ul>
170  * Note that these workarounds are only suggested where {@code lhm} is a
171  * {@code LinkedHashMap}.
172  *
173  * <p>This class is a member of the
174  * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
175  * Java Collections Framework</a>.
176  *
177  * @implNote
178  * The spliterators returned by the spliterator method of the collections
179  * returned by all of this class's collection view methods are created from
180  * the iterators of the corresponding collections.
181  *
182  * @param <K> the type of keys maintained by this map
183  * @param <V> the type of mapped values
184  *
185  * @author  Josh Bloch
186  * @see     Object#hashCode()
187  * @see     Collection
188  * @see     Map
189  * @see     HashMap
190  * @see     TreeMap
191  * @see     Hashtable
192  * @since   1.4
193  */
194 public class LinkedHashMap<K,V>
195     extends HashMap<K,V>
196     implements SequencedMap<K,V>, Map<K, V>
197 {
198 
199     /*
200      * Implementation note.  A previous version of this class was
201      * internally structured a little differently. Because superclass
202      * HashMap now uses trees for some of its nodes, class
203      * LinkedHashMap.Entry is now treated as intermediary node class
204      * that can also be converted to tree form. The name of this
205      * class, LinkedHashMap.Entry, is confusing in several ways in its
206      * current context, but cannot be changed.  Otherwise, even though
207      * it is not exported outside this package, some existing source
208      * code is known to have relied on a symbol resolution corner case
209      * rule in calls to removeEldestEntry that suppressed compilation
210      * errors due to ambiguous usages. So, we keep the name to
211      * preserve unmodified compilability.
212      *
213      * The changes in node classes also require using two fields
214      * (head, tail) rather than a pointer to a header node to maintain
215      * the doubly-linked before/after list. This class also
216      * previously used a different style of callback methods upon
217      * access, insertion, and removal.
218      */
219 
220     /**
221      * HashMap.Node subclass for normal LinkedHashMap entries.
222      */
223     static class Entry<K,V> extends HashMap.Node<K,V> {
224         Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next)225         Entry(int hash, K key, V value, Node<K,V> next) {
226             super(hash, key, value, next);
227         }
228     }
229 
230     @java.io.Serial
231     private static final long serialVersionUID = 3801124242820219131L;
232 
233     /**
234      * The head (eldest) of the doubly linked list.
235      */
236     transient LinkedHashMap.Entry<K,V> head;
237 
238     /**
239      * The tail (youngest) of the doubly linked list.
240      */
241     transient LinkedHashMap.Entry<K,V> tail;
242 
243     /**
244      * The iteration ordering method for this linked hash map: {@code true}
245      * for access-order, {@code false} for insertion-order.
246      *
247      * @serial
248      */
249     final boolean accessOrder;
250 
251     // internal utilities
252 
253     // link at the end of list
linkNodeAtEnd(LinkedHashMap.Entry<K,V> p)254     private void linkNodeAtEnd(LinkedHashMap.Entry<K,V> p) {
255         if (putMode == PUT_FIRST) {
256             LinkedHashMap.Entry<K,V> first = head;
257             head = p;
258             if (first == null)
259                 tail = p;
260             else {
261                 p.after = first;
262                 first.before = p;
263             }
264         } else {
265             LinkedHashMap.Entry<K,V> last = tail;
266             tail = p;
267             if (last == null)
268                 head = p;
269             else {
270                 p.before = last;
271                 last.after = p;
272             }
273         }
274     }
275 
276     // apply src's links to dst
transferLinks(LinkedHashMap.Entry<K,V> src, LinkedHashMap.Entry<K,V> dst)277     private void transferLinks(LinkedHashMap.Entry<K,V> src,
278                                LinkedHashMap.Entry<K,V> dst) {
279         LinkedHashMap.Entry<K,V> b = dst.before = src.before;
280         LinkedHashMap.Entry<K,V> a = dst.after = src.after;
281         if (b == null)
282             head = dst;
283         else
284             b.after = dst;
285         if (a == null)
286             tail = dst;
287         else
288             a.before = dst;
289     }
290 
291     // overrides of HashMap hook methods
292 
reinitialize()293     void reinitialize() {
294         super.reinitialize();
295         head = tail = null;
296     }
297 
newNode(int hash, K key, V value, Node<K,V> e)298     Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
299         LinkedHashMap.Entry<K,V> p =
300             new LinkedHashMap.Entry<>(hash, key, value, e);
301         linkNodeAtEnd(p);
302         return p;
303     }
304 
replacementNode(Node<K,V> p, Node<K,V> next)305     Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
306         LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
307         LinkedHashMap.Entry<K,V> t =
308             new LinkedHashMap.Entry<>(q.hash, q.key, q.value, next);
309         transferLinks(q, t);
310         return t;
311     }
312 
newTreeNode(int hash, K key, V value, Node<K,V> next)313     TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
314         TreeNode<K,V> p = new TreeNode<>(hash, key, value, next);
315         linkNodeAtEnd(p);
316         return p;
317     }
318 
replacementTreeNode(Node<K,V> p, Node<K,V> next)319     TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
320         LinkedHashMap.Entry<K,V> q = (LinkedHashMap.Entry<K,V>)p;
321         TreeNode<K,V> t = new TreeNode<>(q.hash, q.key, q.value, next);
322         transferLinks(q, t);
323         return t;
324     }
325 
afterNodeRemoval(Node<K,V> e)326     void afterNodeRemoval(Node<K,V> e) { // unlink
327         LinkedHashMap.Entry<K,V> p =
328             (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
329         p.before = p.after = null;
330         if (b == null)
331             head = a;
332         else
333             b.after = a;
334         if (a == null)
335             tail = b;
336         else
337             a.before = b;
338     }
339 
afterNodeInsertion(boolean evict)340     void afterNodeInsertion(boolean evict) { // possibly remove eldest
341         LinkedHashMap.Entry<K,V> first;
342         if (evict && (first = head) != null && removeEldestEntry(first)) {
343             K key = first.key;
344             removeNode(hash(key), key, null, false, true);
345         }
346     }
347 
348     static final int PUT_NORM = 0;
349     static final int PUT_FIRST = 1;
350     static final int PUT_LAST = 2;
351     transient int putMode = PUT_NORM;
352 
353     // Called after update, but not after insertion
afterNodeAccess(Node<K,V> e)354     void afterNodeAccess(Node<K,V> e) {
355         LinkedHashMap.Entry<K,V> last;
356         LinkedHashMap.Entry<K,V> first;
357         if ((putMode == PUT_LAST || (putMode == PUT_NORM && accessOrder)) && (last = tail) != e) {
358             // move node to last
359             LinkedHashMap.Entry<K,V> p =
360                 (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
361             p.after = null;
362             if (b == null)
363                 head = a;
364             else
365                 b.after = a;
366             if (a != null)
367                 a.before = b;
368             else
369                 last = b;
370             if (last == null)
371                 head = p;
372             else {
373                 p.before = last;
374                 last.after = p;
375             }
376             tail = p;
377             ++modCount;
378         } else if (putMode == PUT_FIRST && (first = head) != e) {
379             // move node to first
380             LinkedHashMap.Entry<K,V> p =
381                 (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
382             p.before = null;
383             if (a == null)
384                 tail = b;
385             else
386                 a.before = b;
387             if (b != null)
388                 b.after = a;
389             else
390                 first = a;
391             if (first == null)
392                 tail = p;
393             else {
394                 p.after = first;
395                 first.before = p;
396             }
397             head = p;
398             ++modCount;
399         }
400     }
401 
402     /**
403      * {@inheritDoc}
404      * <p>
405      * If this map already contains a mapping for this key, the mapping is relocated if necessary
406      * so that it is first in encounter order.
407      *
408      * @since 21
409      */
putFirst(K k, V v)410     public V putFirst(K k, V v) {
411         try {
412             putMode = PUT_FIRST;
413             return this.put(k, v);
414         } finally {
415             putMode = PUT_NORM;
416         }
417     }
418 
419     /**
420      * {@inheritDoc}
421      * <p>
422      * If this map already contains a mapping for this key, the mapping is relocated if necessary
423      * so that it is last in encounter order.
424      *
425      * @since 21
426      */
putLast(K k, V v)427     public V putLast(K k, V v) {
428         try {
429             putMode = PUT_LAST;
430             return this.put(k, v);
431         } finally {
432             putMode = PUT_NORM;
433         }
434     }
435 
internalWriteEntries(java.io.ObjectOutputStream s)436     void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
437         for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
438             s.writeObject(e.key);
439             s.writeObject(e.value);
440         }
441     }
442 
443     /**
444      * Constructs an empty insertion-ordered {@code LinkedHashMap} instance
445      * with the specified initial capacity and load factor.
446      *
447      * @apiNote
448      * To create a {@code LinkedHashMap} with an initial capacity that accommodates
449      * an expected number of mappings, use {@link #newLinkedHashMap(int) newLinkedHashMap}.
450      *
451      * @param  initialCapacity the initial capacity
452      * @param  loadFactor      the load factor
453      * @throws IllegalArgumentException if the initial capacity is negative
454      *         or the load factor is nonpositive
455      */
LinkedHashMap(int initialCapacity, float loadFactor)456     public LinkedHashMap(int initialCapacity, float loadFactor) {
457         super(initialCapacity, loadFactor);
458         accessOrder = false;
459     }
460 
461     /**
462      * Constructs an empty insertion-ordered {@code LinkedHashMap} instance
463      * with the specified initial capacity and a default load factor (0.75).
464      *
465      * @apiNote
466      * To create a {@code LinkedHashMap} with an initial capacity that accommodates
467      * an expected number of mappings, use {@link #newLinkedHashMap(int) newLinkedHashMap}.
468      *
469      * @param  initialCapacity the initial capacity
470      * @throws IllegalArgumentException if the initial capacity is negative
471      */
LinkedHashMap(int initialCapacity)472     public LinkedHashMap(int initialCapacity) {
473         super(initialCapacity);
474         accessOrder = false;
475     }
476 
477     /**
478      * Constructs an empty insertion-ordered {@code LinkedHashMap} instance
479      * with the default initial capacity (16) and load factor (0.75).
480      */
LinkedHashMap()481     public LinkedHashMap() {
482         super();
483         accessOrder = false;
484     }
485 
486     /**
487      * Constructs an insertion-ordered {@code LinkedHashMap} instance with
488      * the same mappings as the specified map.  The {@code LinkedHashMap}
489      * instance is created with a default load factor (0.75) and an initial
490      * capacity sufficient to hold the mappings in the specified map.
491      *
492      * @param  m the map whose mappings are to be placed in this map
493      * @throws NullPointerException if the specified map is null
494      */
LinkedHashMap(Map<? extends K, ? extends V> m)495     public LinkedHashMap(Map<? extends K, ? extends V> m) {
496         super();
497         accessOrder = false;
498         putMapEntries(m, false);
499     }
500 
501     /**
502      * Constructs an empty {@code LinkedHashMap} instance with the
503      * specified initial capacity, load factor and ordering mode.
504      *
505      * @param  initialCapacity the initial capacity
506      * @param  loadFactor      the load factor
507      * @param  accessOrder     the ordering mode - {@code true} for
508      *         access-order, {@code false} for insertion-order
509      * @throws IllegalArgumentException if the initial capacity is negative
510      *         or the load factor is nonpositive
511      */
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)512     public LinkedHashMap(int initialCapacity,
513                          float loadFactor,
514                          boolean accessOrder) {
515         super(initialCapacity, loadFactor);
516         this.accessOrder = accessOrder;
517     }
518 
519 
520     /**
521      * Returns {@code true} if this map maps one or more keys to the
522      * specified value.
523      *
524      * @param value value whose presence in this map is to be tested
525      * @return {@code true} if this map maps one or more keys to the
526      *         specified value
527      */
containsValue(Object value)528     public boolean containsValue(Object value) {
529         for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
530             V v = e.value;
531             if (v == value || (value != null && value.equals(v)))
532                 return true;
533         }
534         return false;
535     }
536 
537     /**
538      * Returns the value to which the specified key is mapped,
539      * or {@code null} if this map contains no mapping for the key.
540      *
541      * <p>More formally, if this map contains a mapping from a key
542      * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
543      * key.equals(k))}, then this method returns {@code v}; otherwise
544      * it returns {@code null}.  (There can be at most one such mapping.)
545      *
546      * <p>A return value of {@code null} does not <i>necessarily</i>
547      * indicate that the map contains no mapping for the key; it's also
548      * possible that the map explicitly maps the key to {@code null}.
549      * The {@link #containsKey containsKey} operation may be used to
550      * distinguish these two cases.
551      */
get(Object key)552     public V get(Object key) {
553         Node<K,V> e;
554         if ((e = getNode(key)) == null)
555             return null;
556         if (accessOrder)
557             afterNodeAccess(e);
558         return e.value;
559     }
560 
561     /**
562      * {@inheritDoc}
563      */
getOrDefault(Object key, V defaultValue)564     public V getOrDefault(Object key, V defaultValue) {
565        Node<K,V> e;
566        if ((e = getNode(key)) == null)
567            return defaultValue;
568        if (accessOrder)
569            afterNodeAccess(e);
570        return e.value;
571    }
572 
573     /**
574      * {@inheritDoc}
575      */
clear()576     public void clear() {
577         super.clear();
578         head = tail = null;
579     }
580 
581     // Android-added: eldest(), for internal use in LRU caches
582     /**
583      * Returns the eldest entry in the map, or {@code null} if the map is empty.
584      *
585      * @return eldest entry in the map, or {@code null} if the map is empty
586      *
587      * @hide
588      */
eldest()589     public Map.Entry<K, V> eldest() {
590         return head;
591     }
592 
593     /**
594      * Returns {@code true} if this map should remove its eldest entry.
595      * This method is invoked by {@code put} and {@code putAll} after
596      * inserting a new entry into the map.  It provides the implementor
597      * with the opportunity to remove the eldest entry each time a new one
598      * is added.  This is useful if the map represents a cache: it allows
599      * the map to reduce memory consumption by deleting stale entries.
600      *
601      * <p>Sample use: this override will allow the map to grow up to 100
602      * entries and then delete the eldest entry each time a new entry is
603      * added, maintaining a steady state of 100 entries.
604      * <pre>
605      *     private static final int MAX_ENTRIES = 100;
606      *
607      *     protected boolean removeEldestEntry(Map.Entry eldest) {
608      *        return size() &gt; MAX_ENTRIES;
609      *     }
610      * </pre>
611      *
612      * <p>This method typically does not modify the map in any way,
613      * instead allowing the map to modify itself as directed by its
614      * return value.  It <i>is</i> permitted for this method to modify
615      * the map directly, but if it does so, it <i>must</i> return
616      * {@code false} (indicating that the map should not attempt any
617      * further modification).  The effects of returning {@code true}
618      * after modifying the map from within this method are unspecified.
619      *
620      * <p>This implementation merely returns {@code false} (so that this
621      * map acts like a normal map - the eldest element is never removed).
622      *
623      * @param    eldest The least recently inserted entry in the map, or if
624      *           this is an access-ordered map, the least recently accessed
625      *           entry.  This is the entry that will be removed if this
626      *           method returns {@code true}.  If the map was empty prior
627      *           to the {@code put} or {@code putAll} invocation resulting
628      *           in this invocation, this will be the entry that was just
629      *           inserted; in other words, if the map contains a single
630      *           entry, the eldest entry is also the newest.
631      * @return   {@code true} if the eldest entry should be removed
632      *           from the map; {@code false} if it should be retained.
633      */
removeEldestEntry(Map.Entry<K,V> eldest)634     protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
635         return false;
636     }
637 
638     /**
639      * Returns a {@link Set} view of the keys contained in this map. The encounter
640      * order of the keys in the view matches the encounter order of mappings of
641      * this map. The set is backed by the map, so changes to the map are
642      * reflected in the set, and vice-versa.  If the map is modified
643      * while an iteration over the set is in progress (except through
644      * the iterator's own {@code remove} operation), the results of
645      * the iteration are undefined.  The set supports element removal,
646      * which removes the corresponding mapping from the map, via the
647      * {@code Iterator.remove}, {@code Set.remove},
648      * {@code removeAll}, {@code retainAll}, and {@code clear}
649      * operations.  It does not support the {@code add} or {@code addAll}
650      * operations.
651      * Its {@link Spliterator} typically provides faster sequential
652      * performance but much poorer parallel performance than that of
653      * {@code HashMap}.
654      *
655      * @return a set view of the keys contained in this map
656      */
keySet()657     public Set<K> keySet() {
658         return sequencedKeySet();
659     }
660 
661     /**
662      * {@inheritDoc}
663      * <p>
664      * The returned view has the same characteristics as specified for the view
665      * returned by the {@link #keySet keySet} method.
666      *
667      * @return {@inheritDoc}
668      * @since 21
669      */
sequencedKeySet()670     public SequencedSet<K> sequencedKeySet() {
671         Set<K> ks = keySet;
672         if (ks == null) {
673             SequencedSet<K> sks = new LinkedKeySet(false);
674             keySet = sks;
675             return sks;
676         } else {
677             // The cast should never fail, since the only assignment of non-null to keySet is
678             // above, and assignments in AbstractMap and HashMap are in overridden methods.
679             return (SequencedSet<K>) ks;
680         }
681     }
682 
nsee(Node<K1,V1> node)683     static <K1,V1> Node<K1,V1> nsee(Node<K1,V1> node) {
684         if (node == null)
685             throw new NoSuchElementException();
686         else
687             return node;
688     }
689 
keysToArray(T[] a)690     final <T> T[] keysToArray(T[] a) {
691         return keysToArray(a, false);
692     }
693 
keysToArray(T[] a, boolean reversed)694     final <T> T[] keysToArray(T[] a, boolean reversed) {
695         Object[] r = a;
696         int idx = 0;
697         if (reversed) {
698             for (LinkedHashMap.Entry<K,V> e = tail; e != null; e = e.before) {
699                 r[idx++] = e.key;
700             }
701         } else {
702             for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
703                 r[idx++] = e.key;
704             }
705         }
706         return a;
707     }
708 
valuesToArray(T[] a, boolean reversed)709     final <T> T[] valuesToArray(T[] a, boolean reversed) {
710         Object[] r = a;
711         int idx = 0;
712         if (reversed) {
713             for (LinkedHashMap.Entry<K,V> e = tail; e != null; e = e.before) {
714                 r[idx++] = e.value;
715             }
716         } else {
717             for (LinkedHashMap.Entry<K,V> e = head; e != null; e = e.after) {
718                 r[idx++] = e.value;
719             }
720         }
721         return a;
722     }
723 
724     final class LinkedKeySet extends AbstractSet<K> implements SequencedSet<K> {
725         final boolean reversed;
LinkedKeySet(boolean reversed)726         LinkedKeySet(boolean reversed)          { this.reversed = reversed; }
size()727         public final int size()                 { return size; }
clear()728         public final void clear()               { LinkedHashMap.this.clear(); }
iterator()729         public final Iterator<K> iterator() {
730             return new LinkedKeyIterator(reversed);
731         }
contains(Object o)732         public final boolean contains(Object o) { return containsKey(o); }
remove(Object key)733         public final boolean remove(Object key) {
734             return removeNode(hash(key), key, null, false, true) != null;
735         }
spliterator()736         public final Spliterator<K> spliterator()  {
737             return Spliterators.spliterator(this, Spliterator.SIZED |
738                                             Spliterator.ORDERED |
739                                             Spliterator.DISTINCT);
740         }
741 
toArray()742         public Object[] toArray() {
743             return keysToArray(new Object[size], reversed);
744         }
745 
toArray(T[] a)746         public <T> T[] toArray(T[] a) {
747             return keysToArray(prepareArray(a), reversed);
748         }
749 
forEach(Consumer<? super K> action)750         public final void forEach(Consumer<? super K> action) {
751             if (action == null)
752                 throw new NullPointerException();
753             int mc = modCount;
754             if (reversed) {
755                 // Android-changed: Detect changes to modCount early.
756                 for (LinkedHashMap.Entry<K,V> e = tail; e != null && modCount == mc; e = e.before)
757                     action.accept(e.key);
758             } else {
759                 // Android-changed: Detect changes to modCount early.
760                 for (LinkedHashMap.Entry<K,V> e = head; (e != null && modCount == mc); e = e.after)
761                     action.accept(e.key);
762             }
763             if (modCount != mc)
764                 throw new ConcurrentModificationException();
765         }
addFirst(K k)766         public final void addFirst(K k) { throw new UnsupportedOperationException(); }
addLast(K k)767         public final void addLast(K k) { throw new UnsupportedOperationException(); }
getFirst()768         public final K getFirst() { return nsee(reversed ? tail : head).key; }
getLast()769         public final K getLast() { return nsee(reversed ? head : tail).key; }
removeFirst()770         public final K removeFirst() {
771             var node = nsee(reversed ? tail : head);
772             removeNode(node.hash, node.key, null, false, false);
773             return node.key;
774         }
removeLast()775         public final K removeLast() {
776             var node = nsee(reversed ? head : tail);
777             removeNode(node.hash, node.key, null, false, false);
778             return node.key;
779         }
reversed()780         public SequencedSet<K> reversed() {
781             if (reversed) {
782                 return LinkedHashMap.this.sequencedKeySet();
783             } else {
784                 return new LinkedKeySet(true);
785             }
786         }
787     }
788 
789     /**
790      * Returns a {@link Collection} view of the values contained in this map. The
791      * encounter order of values in the view matches the encounter order of entries in
792      * this map. The collection is backed by the map, so changes to the map are
793      * reflected in the collection, and vice-versa.  If the map is
794      * modified while an iteration over the collection is in progress
795      * (except through the iterator's own {@code remove} operation),
796      * the results of the iteration are undefined.  The collection
797      * supports element removal, which removes the corresponding
798      * mapping from the map, via the {@code Iterator.remove},
799      * {@code Collection.remove}, {@code removeAll},
800      * {@code retainAll} and {@code clear} operations.  It does not
801      * support the {@code add} or {@code addAll} operations.
802      * Its {@link Spliterator} typically provides faster sequential
803      * performance but much poorer parallel performance than that of
804      * {@code HashMap}.
805      *
806      * @return a view of the values contained in this map
807      */
values()808     public Collection<V> values() {
809         return sequencedValues();
810     }
811 
812     /**
813      * {@inheritDoc}
814      * <p>
815      * The returned view has the same characteristics as specified for the view
816      * returned by the {@link #values values} method.
817      *
818      * @return {@inheritDoc}
819      * @since 21
820      */
sequencedValues()821     public SequencedCollection<V> sequencedValues() {
822         Collection<V> vs = values;
823         if (vs == null) {
824             SequencedCollection<V> svs = new LinkedValues(false);
825             values = svs;
826             return svs;
827         } else {
828             // The cast should never fail, since the only assignment of non-null to values is
829             // above, and assignments in AbstractMap and HashMap are in overridden methods.
830             return (SequencedCollection<V>) vs;
831         }
832     }
833 
834     final class LinkedValues extends AbstractCollection<V> implements SequencedCollection<V> {
835         final boolean reversed;
LinkedValues(boolean reversed)836         LinkedValues(boolean reversed)          { this.reversed = reversed; }
size()837         public final int size()                 { return size; }
clear()838         public final void clear()               { LinkedHashMap.this.clear(); }
iterator()839         public final Iterator<V> iterator() {
840             return new LinkedValueIterator(reversed);
841         }
contains(Object o)842         public final boolean contains(Object o) { return containsValue(o); }
spliterator()843         public final Spliterator<V> spliterator() {
844             return Spliterators.spliterator(this, Spliterator.SIZED |
845                                             Spliterator.ORDERED);
846         }
847 
toArray()848         public Object[] toArray() {
849             return valuesToArray(new Object[size], reversed);
850         }
851 
toArray(T[] a)852         public <T> T[] toArray(T[] a) {
853             return valuesToArray(prepareArray(a), reversed);
854         }
855 
forEach(Consumer<? super V> action)856         public final void forEach(Consumer<? super V> action) {
857             if (action == null)
858                 throw new NullPointerException();
859             int mc = modCount;
860             if (reversed) {
861                 // Android-changed: Detect changes to modCount early.
862                 for (LinkedHashMap.Entry<K,V> e = tail; e != null && modCount == mc; e = e.before)
863                     action.accept(e.value);
864             } else {
865                 // Android-changed: Detect changes to modCount early.
866                 for (LinkedHashMap.Entry<K,V> e = head; (e != null && modCount == mc); e = e.after)
867                     action.accept(e.value);
868             }
869             if (modCount != mc)
870                 throw new ConcurrentModificationException();
871         }
addFirst(V v)872         public final void addFirst(V v) { throw new UnsupportedOperationException(); }
addLast(V v)873         public final void addLast(V v) { throw new UnsupportedOperationException(); }
getFirst()874         public final V getFirst() { return nsee(reversed ? tail : head).value; }
getLast()875         public final V getLast() { return nsee(reversed ? head : tail).value; }
removeFirst()876         public final V removeFirst() {
877             var node = nsee(reversed ? tail : head);
878             removeNode(node.hash, node.key, null, false, false);
879             return node.value;
880         }
removeLast()881         public final V removeLast() {
882             var node = nsee(reversed ? head : tail);
883             removeNode(node.hash, node.key, null, false, false);
884             return node.value;
885         }
reversed()886         public SequencedCollection<V> reversed() {
887             if (reversed) {
888                 return LinkedHashMap.this.sequencedValues();
889             } else {
890                 return new LinkedValues(true);
891             }
892         }
893     }
894 
895     /**
896      * Returns a {@link Set} view of the mappings contained in this map. The encounter
897      * order of the view matches the encounter order of entries of this map.
898      * The set is backed by the map, so changes to the map are
899      * reflected in the set, and vice-versa.  If the map is modified
900      * while an iteration over the set is in progress (except through
901      * the iterator's own {@code remove} operation, or through the
902      * {@code setValue} operation on a map entry returned by the
903      * iterator) the results of the iteration are undefined.  The set
904      * supports element removal, which removes the corresponding
905      * mapping from the map, via the {@code Iterator.remove},
906      * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
907      * {@code clear} operations.  It does not support the
908      * {@code add} or {@code addAll} operations.
909      * Its {@link Spliterator} typically provides faster sequential
910      * performance but much poorer parallel performance than that of
911      * {@code HashMap}.
912      *
913      * @return a set view of the mappings contained in this map
914      */
entrySet()915     public Set<Map.Entry<K,V>> entrySet() {
916         return sequencedEntrySet();
917     }
918 
919     /**
920      * {@inheritDoc}
921      * <p>
922      * The returned view has the same characteristics as specified for the view
923      * returned by the {@link #entrySet entrySet} method.
924      *
925      * @return {@inheritDoc}
926      * @since 21
927      */
sequencedEntrySet()928     public SequencedSet<Map.Entry<K, V>> sequencedEntrySet() {
929         Set<Map.Entry<K, V>> es = entrySet;
930         if (es == null) {
931             SequencedSet<Map.Entry<K, V>> ses = new LinkedEntrySet(false);
932             entrySet = ses;
933             return ses;
934         } else {
935             // The cast should never fail, since the only assignment of non-null to entrySet is
936             // above, and assignments in HashMap are in overridden methods.
937             return (SequencedSet<Map.Entry<K, V>>) es;
938         }
939     }
940 
941     final class LinkedEntrySet extends AbstractSet<Map.Entry<K,V>>
942         implements SequencedSet<Map.Entry<K,V>> {
943         final boolean reversed;
LinkedEntrySet(boolean reversed)944         LinkedEntrySet(boolean reversed)        { this.reversed = reversed; }
size()945         public final int size()                 { return size; }
clear()946         public final void clear()               { LinkedHashMap.this.clear(); }
iterator()947         public final Iterator<Map.Entry<K,V>> iterator() {
948             return new LinkedEntryIterator(reversed);
949         }
contains(Object o)950         public final boolean contains(Object o) {
951             if (!(o instanceof Map.Entry<?, ?> e))
952                 return false;
953             Object key = e.getKey();
954             Node<K,V> candidate = getNode(key);
955             return candidate != null && candidate.equals(e);
956         }
remove(Object o)957         public final boolean remove(Object o) {
958             if (o instanceof Map.Entry<?, ?> e) {
959                 Object key = e.getKey();
960                 Object value = e.getValue();
961                 return removeNode(hash(key), key, value, true, true) != null;
962             }
963             return false;
964         }
spliterator()965         public final Spliterator<Map.Entry<K,V>> spliterator() {
966             return Spliterators.spliterator(this, Spliterator.SIZED |
967                                             Spliterator.ORDERED |
968                                             Spliterator.DISTINCT);
969         }
forEach(Consumer<? super Map.Entry<K,V>> action)970         public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
971             if (action == null)
972                 throw new NullPointerException();
973             int mc = modCount;
974             if (reversed) {
975                 // Android-changed: Detect changes to modCount early.
976                 for (LinkedHashMap.Entry<K,V> e = tail; e != null && mc == modCount; e = e.before)
977                     action.accept(e);
978             } else {
979                 // Android-changed: Detect changes to modCount early.
980                 for (LinkedHashMap.Entry<K,V> e = head; (e != null && mc == modCount); e = e.after)
981                     action.accept(e);
982             }
983             if (modCount != mc)
984                 throw new ConcurrentModificationException();
985         }
nsee(Node<K,V> e)986         final Node<K,V> nsee(Node<K,V> e) {
987             if (e == null)
988                 throw new NoSuchElementException();
989             else
990                 return e;
991         }
addFirst(Map.Entry<K,V> e)992         public final void addFirst(Map.Entry<K,V> e) { throw new UnsupportedOperationException(); }
addLast(Map.Entry<K,V> e)993         public final void addLast(Map.Entry<K,V> e) { throw new UnsupportedOperationException(); }
getFirst()994         public final Map.Entry<K,V> getFirst() { return nsee(reversed ? tail : head); }
getLast()995         public final Map.Entry<K,V> getLast() { return nsee(reversed ? head : tail); }
removeFirst()996         public final Map.Entry<K,V> removeFirst() {
997             var node = nsee(reversed ? tail : head);
998             removeNode(node.hash, node.key, null, false, false);
999             return node;
1000         }
removeLast()1001         public final Map.Entry<K,V> removeLast() {
1002             var node = nsee(reversed ? head : tail);
1003             removeNode(node.hash, node.key, null, false, false);
1004             return node;
1005         }
reversed()1006         public SequencedSet<Map.Entry<K,V>> reversed() {
1007             if (reversed) {
1008                 return LinkedHashMap.this.sequencedEntrySet();
1009             } else {
1010                 return new LinkedEntrySet(true);
1011             }
1012         }
1013     }
1014 
1015     // Map overrides
1016 
forEach(BiConsumer<? super K, ? super V> action)1017     public void forEach(BiConsumer<? super K, ? super V> action) {
1018         if (action == null)
1019             throw new NullPointerException();
1020         int mc = modCount;
1021         // Android-changed: Detect changes to modCount early.
1022         for (LinkedHashMap.Entry<K,V> e = head; modCount == mc && e != null; e = e.after)
1023             action.accept(e.key, e.value);
1024         if (modCount != mc)
1025             throw new ConcurrentModificationException();
1026     }
1027 
replaceAll(BiFunction<? super K, ? super V, ? extends V> function)1028     public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
1029         if (function == null)
1030             throw new NullPointerException();
1031         int mc = modCount;
1032         // Android-changed: Detect changes to modCount early.
1033         for (LinkedHashMap.Entry<K,V> e = head; modCount == mc && e != null; e = e.after)
1034             e.value = function.apply(e.key, e.value);
1035         if (modCount != mc)
1036             throw new ConcurrentModificationException();
1037     }
1038 
1039     // Iterators
1040 
1041     abstract class LinkedHashIterator {
1042         LinkedHashMap.Entry<K,V> next;
1043         LinkedHashMap.Entry<K,V> current;
1044         int expectedModCount;
1045         boolean reversed;
1046 
LinkedHashIterator(boolean reversed)1047         LinkedHashIterator(boolean reversed) {
1048             this.reversed = reversed;
1049             next = reversed ? tail : head;
1050             expectedModCount = modCount;
1051             current = null;
1052         }
1053 
hasNext()1054         public final boolean hasNext() {
1055             return next != null;
1056         }
1057 
nextNode()1058         final LinkedHashMap.Entry<K,V> nextNode() {
1059             LinkedHashMap.Entry<K,V> e = next;
1060             if (modCount != expectedModCount)
1061                 throw new ConcurrentModificationException();
1062             if (e == null)
1063                 throw new NoSuchElementException();
1064             current = e;
1065             next = reversed ? e.before : e.after;
1066             return e;
1067         }
1068 
remove()1069         public final void remove() {
1070             Node<K,V> p = current;
1071             if (p == null)
1072                 throw new IllegalStateException();
1073             if (modCount != expectedModCount)
1074                 throw new ConcurrentModificationException();
1075             current = null;
1076             removeNode(p.hash, p.key, null, false, false);
1077             expectedModCount = modCount;
1078         }
1079     }
1080 
1081     final class LinkedKeyIterator extends LinkedHashIterator
1082         implements Iterator<K> {
LinkedKeyIterator(boolean reversed)1083         LinkedKeyIterator(boolean reversed) { super(reversed); }
next()1084         public final K next() { return nextNode().getKey(); }
1085     }
1086 
1087     final class LinkedValueIterator extends LinkedHashIterator
1088         implements Iterator<V> {
LinkedValueIterator(boolean reversed)1089         LinkedValueIterator(boolean reversed) { super(reversed); }
next()1090         public final V next() { return nextNode().value; }
1091     }
1092 
1093     final class LinkedEntryIterator extends LinkedHashIterator
1094         implements Iterator<Map.Entry<K,V>> {
LinkedEntryIterator(boolean reversed)1095         LinkedEntryIterator(boolean reversed) { super(reversed); }
next()1096         public final Map.Entry<K,V> next() { return nextNode(); }
1097     }
1098 
1099     /**
1100      * Creates a new, empty, insertion-ordered LinkedHashMap suitable for the expected number of mappings.
1101      * The returned map uses the default load factor of 0.75, and its initial capacity is
1102      * generally large enough so that the expected number of mappings can be added
1103      * without resizing the map.
1104      *
1105      * @param numMappings the expected number of mappings
1106      * @param <K>         the type of keys maintained by the new map
1107      * @param <V>         the type of mapped values
1108      * @return the newly created map
1109      * @throws IllegalArgumentException if numMappings is negative
1110      * @since 19
1111      */
newLinkedHashMap(int numMappings)1112     public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(int numMappings) {
1113         if (numMappings < 0) {
1114             throw new IllegalArgumentException("Negative number of mappings: " + numMappings);
1115         }
1116         return new LinkedHashMap<>(HashMap.calculateHashMapCapacity(numMappings));
1117     }
1118 
1119     // Reversed View
1120 
1121     /**
1122      * {@inheritDoc}
1123      * <p>
1124      * Modifications to the reversed view and its map views are permitted and will be
1125      * propagated to this map. In addition, modifications to this map will be visible
1126      * in the reversed view and its map views.
1127      *
1128      * @return {@inheritDoc}
1129      * @since 21
1130      */
reversed()1131     public SequencedMap<K, V> reversed() {
1132         return new ReversedLinkedHashMapView<>(this);
1133     }
1134 
1135     static class ReversedLinkedHashMapView<K, V> extends AbstractMap<K, V>
1136                                                  implements SequencedMap<K, V> {
1137         final LinkedHashMap<K, V> base;
1138 
ReversedLinkedHashMapView(LinkedHashMap<K, V> lhm)1139         ReversedLinkedHashMapView(LinkedHashMap<K, V> lhm) {
1140             base = lhm;
1141         }
1142 
1143         // Object
1144         // inherit toString() from AbstractMap; it depends on entrySet()
1145 
equals(Object o)1146         public boolean equals(Object o) {
1147             return base.equals(o);
1148         }
1149 
hashCode()1150         public int hashCode() {
1151             return base.hashCode();
1152         }
1153 
1154         // Map
1155 
size()1156         public int size() {
1157             return base.size();
1158         }
1159 
isEmpty()1160         public boolean isEmpty() {
1161             return base.isEmpty();
1162         }
1163 
containsKey(Object key)1164         public boolean containsKey(Object key) {
1165             return base.containsKey(key);
1166         }
1167 
containsValue(Object value)1168         public boolean containsValue(Object value) {
1169             return base.containsValue(value);
1170         }
1171 
get(Object key)1172         public V get(Object key) {
1173             return base.get(key);
1174         }
1175 
put(K key, V value)1176         public V put(K key, V value) {
1177             return base.put(key, value);
1178         }
1179 
remove(Object key)1180         public V remove(Object key) {
1181             return base.remove(key);
1182         }
1183 
putAll(Map<? extends K, ? extends V> m)1184         public void putAll(Map<? extends K, ? extends V> m) {
1185             base.putAll(m);
1186         }
1187 
clear()1188         public void clear() {
1189             base.clear();
1190         }
1191 
keySet()1192         public Set<K> keySet() {
1193             return base.sequencedKeySet().reversed();
1194         }
1195 
values()1196         public Collection<V> values() {
1197             return base.sequencedValues().reversed();
1198         }
1199 
entrySet()1200         public Set<Entry<K, V>> entrySet() {
1201             return base.sequencedEntrySet().reversed();
1202         }
1203 
getOrDefault(Object key, V defaultValue)1204         public V getOrDefault(Object key, V defaultValue) {
1205             return base.getOrDefault(key, defaultValue);
1206         }
1207 
forEach(BiConsumer<? super K, ? super V> action)1208         public void forEach(BiConsumer<? super K, ? super V> action) {
1209             if (action == null)
1210                 throw new NullPointerException();
1211             int mc = base.modCount;
1212             for (LinkedHashMap.Entry<K,V> e = base.tail; e != null; e = e.before)
1213                 action.accept(e.key, e.value);
1214             if (base.modCount != mc)
1215                 throw new ConcurrentModificationException();
1216         }
1217 
replaceAll(BiFunction<? super K, ? super V, ? extends V> function)1218         public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
1219             if (function == null)
1220                 throw new NullPointerException();
1221             int mc = base.modCount;
1222             for (LinkedHashMap.Entry<K,V> e = base.tail; e != null; e = e.before)
1223                 e.value = function.apply(e.key, e.value);
1224             if (base.modCount != mc)
1225                 throw new ConcurrentModificationException();
1226         }
1227 
putIfAbsent(K key, V value)1228         public V putIfAbsent(K key, V value) {
1229             return base.putIfAbsent(key, value);
1230         }
1231 
remove(Object key, Object value)1232         public boolean remove(Object key, Object value) {
1233             return base.remove(key, value);
1234         }
1235 
replace(K key, V oldValue, V newValue)1236         public boolean replace(K key, V oldValue, V newValue) {
1237             return base.replace(key, oldValue, newValue);
1238         }
1239 
replace(K key, V value)1240         public V replace(K key, V value) {
1241             return base.replace(key, value);
1242         }
1243 
computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)1244         public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
1245             return base.computeIfAbsent(key, mappingFunction);
1246         }
1247 
computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)1248         public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
1249             return base.computeIfPresent(key, remappingFunction);
1250         }
1251 
compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)1252         public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
1253             return base.compute(key, remappingFunction);
1254         }
1255 
merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)1256         public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
1257             return base.merge(key, value, remappingFunction);
1258         }
1259 
1260         // SequencedMap
1261 
reversed()1262         public SequencedMap<K, V> reversed() {
1263             return base;
1264         }
1265 
firstEntry()1266         public Entry<K, V> firstEntry() {
1267             return base.lastEntry();
1268         }
1269 
lastEntry()1270         public Entry<K, V> lastEntry() {
1271             return base.firstEntry();
1272         }
1273 
pollFirstEntry()1274         public Entry<K, V> pollFirstEntry() {
1275             return base.pollLastEntry();
1276         }
1277 
pollLastEntry()1278         public Entry<K, V> pollLastEntry() {
1279             return base.pollFirstEntry();
1280         }
1281 
putFirst(K k, V v)1282         public V putFirst(K k, V v) {
1283             return base.putLast(k, v);
1284         }
1285 
putLast(K k, V v)1286         public V putLast(K k, V v) {
1287             return base.putFirst(k, v);
1288         }
1289     }
1290 }
1291