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() > 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