1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. Oracle designates this 9 * particular file as subject to the "Classpath" exception as provided 10 * by Oracle in the LICENSE file that accompanied this code. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 */ 26 27 package java.util; 28 29 import java.io.Serializable; 30 import java.util.function.BiConsumer; 31 import java.util.function.BiFunction; 32 import java.util.function.Consumer; 33 import java.util.function.Function; 34 35 /** 36 * A Red-Black tree based {@link NavigableMap} implementation. 37 * The map is sorted according to the {@linkplain Comparable natural 38 * ordering} of its keys, or by a {@link Comparator} provided at map 39 * creation time, depending on which constructor is used. 40 * 41 * <p>This implementation provides guaranteed log(n) time cost for the 42 * {@code containsKey}, {@code get}, {@code put} and {@code remove} 43 * operations. Algorithms are adaptations of those in Cormen, Leiserson, and 44 * Rivest's <em>Introduction to Algorithms</em>. 45 * 46 * <p>Note that the ordering maintained by a tree map, like any sorted map, and 47 * whether or not an explicit comparator is provided, must be <em>consistent 48 * with {@code equals}</em> if this sorted map is to correctly implement the 49 * {@code Map} interface. (See {@code Comparable} or {@code Comparator} for a 50 * precise definition of <em>consistent with equals</em>.) This is so because 51 * the {@code Map} interface is defined in terms of the {@code equals} 52 * operation, but a sorted map performs all key comparisons using its {@code 53 * compareTo} (or {@code compare}) method, so two keys that are deemed equal by 54 * this method are, from the standpoint of the sorted map, equal. The behavior 55 * of a sorted map <em>is</em> well-defined even if its ordering is 56 * inconsistent with {@code equals}; it just fails to obey the general contract 57 * of the {@code Map} interface. 58 * 59 * <p><strong>Note that this implementation is not synchronized.</strong> 60 * If multiple threads access a map concurrently, and at least one of the 61 * threads modifies the map structurally, it <em>must</em> be synchronized 62 * externally. (A structural modification is any operation that adds or 63 * deletes one or more mappings; merely changing the value associated 64 * with an existing key is not a structural modification.) This is 65 * typically accomplished by synchronizing on some object that naturally 66 * encapsulates the map. 67 * If no such object exists, the map should be "wrapped" using the 68 * {@link Collections#synchronizedSortedMap Collections.synchronizedSortedMap} 69 * method. This is best done at creation time, to prevent accidental 70 * unsynchronized access to the map: <pre> 71 * SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));</pre> 72 * 73 * <p>The iterators returned by the {@code iterator} method of the collections 74 * returned by all of this class's "collection view methods" are 75 * <em>fail-fast</em>: if the map is structurally modified at any time after 76 * the iterator is created, in any way except through the iterator's own 77 * {@code remove} method, the iterator will throw a {@link 78 * ConcurrentModificationException}. Thus, in the face of concurrent 79 * modification, the iterator fails quickly and cleanly, rather than risking 80 * arbitrary, non-deterministic behavior at an undetermined time in the future. 81 * 82 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed 83 * as it is, generally speaking, impossible to make any hard guarantees in the 84 * presence of unsynchronized concurrent modification. Fail-fast iterators 85 * throw {@code ConcurrentModificationException} on a best-effort basis. 86 * Therefore, it would be wrong to write a program that depended on this 87 * exception for its correctness: <em>the fail-fast behavior of iterators 88 * should be used only to detect bugs.</em> 89 * 90 * <p>The methods 91 * {@link #ceilingEntry}, 92 * {@link #firstEntry}, 93 * {@link #floorEntry}, 94 * {@link #higherEntry}, 95 * {@link #lastEntry}, 96 * {@link #lowerEntry}, 97 * {@link #pollFirstEntry}, and 98 * {@link #pollLastEntry} 99 * return {@link Map.Entry} instances that represent snapshots of mappings as 100 * of the time of the call. They do <em>not</em> support mutation of the 101 * underlying map via the optional {@link Map.Entry#setValue setValue} method. 102 * 103 * <p>The {@link #putFirst putFirst} and {@link #putLast putLast} methods of this class 104 * throw {@code UnsupportedOperationException}. The encounter order of mappings is determined 105 * by the comparison method; therefore, explicit positioning is not supported. 106 * 107 * <p>This class is a member of the 108 * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework"> 109 * Java Collections Framework</a>. 110 * 111 * @param <K> the type of keys maintained by this map 112 * @param <V> the type of mapped values 113 * 114 * @author Josh Bloch and Doug Lea 115 * @see Map 116 * @see HashMap 117 * @see Hashtable 118 * @see Comparable 119 * @see Comparator 120 * @see Collection 121 * @since 1.2 122 */ 123 124 public class TreeMap<K,V> 125 extends AbstractMap<K,V> 126 implements NavigableMap<K,V>, Cloneable, java.io.Serializable 127 { 128 /** 129 * The comparator used to maintain order in this tree map, or 130 * null if it uses the natural ordering of its keys. 131 * 132 * @serial 133 */ 134 @SuppressWarnings("serial") // Conditionally serializable 135 private final Comparator<? super K> comparator; 136 137 private transient TreeMapEntry<K,V> root; 138 139 /** 140 * The number of entries in the tree 141 */ 142 private transient int size = 0; 143 144 /** 145 * The number of structural modifications to the tree. 146 */ 147 private transient int modCount = 0; 148 149 /** 150 * Constructs a new, empty tree map, using the natural ordering of its 151 * keys. All keys inserted into the map must implement the {@link 152 * Comparable} interface. Furthermore, all such keys must be 153 * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw 154 * a {@code ClassCastException} for any keys {@code k1} and 155 * {@code k2} in the map. If the user attempts to put a key into the 156 * map that violates this constraint (for example, the user attempts to 157 * put a string key into a map whose keys are integers), the 158 * {@code put(Object key, Object value)} call will throw a 159 * {@code ClassCastException}. 160 */ TreeMap()161 public TreeMap() { 162 comparator = null; 163 } 164 165 /** 166 * Constructs a new, empty tree map, ordered according to the given 167 * comparator. All keys inserted into the map must be <em>mutually 168 * comparable</em> by the given comparator: {@code comparator.compare(k1, 169 * k2)} must not throw a {@code ClassCastException} for any keys 170 * {@code k1} and {@code k2} in the map. If the user attempts to put 171 * a key into the map that violates this constraint, the {@code put(Object 172 * key, Object value)} call will throw a 173 * {@code ClassCastException}. 174 * 175 * @param comparator the comparator that will be used to order this map. 176 * If {@code null}, the {@linkplain Comparable natural 177 * ordering} of the keys will be used. 178 */ TreeMap(Comparator<? super K> comparator)179 public TreeMap(Comparator<? super K> comparator) { 180 this.comparator = comparator; 181 } 182 183 /** 184 * Constructs a new tree map containing the same mappings as the given 185 * map, ordered according to the <em>natural ordering</em> of its keys. 186 * All keys inserted into the new map must implement the {@link 187 * Comparable} interface. Furthermore, all such keys must be 188 * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw 189 * a {@code ClassCastException} for any keys {@code k1} and 190 * {@code k2} in the map. This method runs in n*log(n) time. 191 * 192 * @param m the map whose mappings are to be placed in this map 193 * @throws ClassCastException if the keys in m are not {@link Comparable}, 194 * or are not mutually comparable 195 * @throws NullPointerException if the specified map is null 196 */ TreeMap(Map<? extends K, ? extends V> m)197 public TreeMap(Map<? extends K, ? extends V> m) { 198 comparator = null; 199 putAll(m); 200 } 201 202 /** 203 * Constructs a new tree map containing the same mappings and 204 * using the same ordering as the specified sorted map. This 205 * method runs in linear time. 206 * 207 * @param m the sorted map whose mappings are to be placed in this map, 208 * and whose comparator is to be used to sort this map 209 * @throws NullPointerException if the specified map is null 210 */ TreeMap(SortedMap<K, ? extends V> m)211 public TreeMap(SortedMap<K, ? extends V> m) { 212 comparator = m.comparator(); 213 try { 214 buildFromSorted(m.size(), m.entrySet().iterator(), null, null); 215 } catch (java.io.IOException | ClassNotFoundException cannotHappen) { 216 } 217 } 218 219 220 // Query Operations 221 222 /** 223 * Returns the number of key-value mappings in this map. 224 * 225 * @return the number of key-value mappings in this map 226 */ size()227 public int size() { 228 return size; 229 } 230 231 /** 232 * Returns {@code true} if this map contains a mapping for the specified 233 * key. 234 * 235 * @param key key whose presence in this map is to be tested 236 * @return {@code true} if this map contains a mapping for the 237 * specified key 238 * @throws ClassCastException if the specified key cannot be compared 239 * with the keys currently in the map 240 * @throws NullPointerException if the specified key is null 241 * and this map uses natural ordering, or its comparator 242 * does not permit null keys 243 */ containsKey(Object key)244 public boolean containsKey(Object key) { 245 return getEntry(key) != null; 246 } 247 248 /** 249 * Returns {@code true} if this map maps one or more keys to the 250 * specified value. More formally, returns {@code true} if and only if 251 * this map contains at least one mapping to a value {@code v} such 252 * that {@code (value==null ? v==null : value.equals(v))}. This 253 * operation will probably require time linear in the map size for 254 * most implementations. 255 * 256 * @param value value whose presence in this map is to be tested 257 * @return {@code true} if a mapping to {@code value} exists; 258 * {@code false} otherwise 259 * @since 1.2 260 */ containsValue(Object value)261 public boolean containsValue(Object value) { 262 for (TreeMapEntry<K,V> e = getFirstEntry(); e != null; e = successor(e)) 263 if (valEquals(value, e.value)) 264 return true; 265 return false; 266 } 267 268 /** 269 * Returns the value to which the specified key is mapped, 270 * or {@code null} if this map contains no mapping for the key. 271 * 272 * <p>More formally, if this map contains a mapping from a key 273 * {@code k} to a value {@code v} such that {@code key} compares 274 * equal to {@code k} according to the map's ordering, then this 275 * method returns {@code v}; otherwise it returns {@code null}. 276 * (There can be at most one such mapping.) 277 * 278 * <p>A return value of {@code null} does not <em>necessarily</em> 279 * indicate that the map contains no mapping for the key; it's also 280 * possible that the map explicitly maps the key to {@code null}. 281 * The {@link #containsKey containsKey} operation may be used to 282 * distinguish these two cases. 283 * 284 * @throws ClassCastException if the specified key cannot be compared 285 * with the keys currently in the map 286 * @throws NullPointerException if the specified key is null 287 * and this map uses natural ordering, or its comparator 288 * does not permit null keys 289 */ get(Object key)290 public V get(Object key) { 291 TreeMapEntry<K,V> p = getEntry(key); 292 return (p==null ? null : p.value); 293 } 294 comparator()295 public Comparator<? super K> comparator() { 296 return comparator; 297 } 298 299 /** 300 * @throws NoSuchElementException {@inheritDoc} 301 */ firstKey()302 public K firstKey() { 303 return key(getFirstEntry()); 304 } 305 306 /** 307 * @throws NoSuchElementException {@inheritDoc} 308 */ lastKey()309 public K lastKey() { 310 return key(getLastEntry()); 311 } 312 313 /** 314 * Throws {@code UnsupportedOperationException}. The encounter order induced by this 315 * map's comparison method determines the position of mappings, so explicit positioning 316 * is not supported. 317 * 318 * @throws UnsupportedOperationException always 319 * @since 21 320 */ putFirst(K k, V v)321 public V putFirst(K k, V v) { 322 throw new UnsupportedOperationException(); 323 } 324 325 /** 326 * Throws {@code UnsupportedOperationException}. The encounter order induced by this 327 * map's comparison method determines the position of mappings, so explicit positioning 328 * is not supported. 329 * 330 * @throws UnsupportedOperationException always 331 * @since 21 332 */ putLast(K k, V v)333 public V putLast(K k, V v) { 334 throw new UnsupportedOperationException(); 335 } 336 337 /** 338 * Copies all of the mappings from the specified map to this map. 339 * These mappings replace any mappings that this map had for any 340 * of the keys currently in the specified map. 341 * 342 * @param map mappings to be stored in this map 343 * @throws ClassCastException if the class of a key or value in 344 * the specified map prevents it from being stored in this map 345 * @throws NullPointerException if the specified map is null or 346 * the specified map contains a null key and this map does not 347 * permit null keys 348 */ putAll(Map<? extends K, ? extends V> map)349 public void putAll(Map<? extends K, ? extends V> map) { 350 int mapSize = map.size(); 351 if (size==0 && mapSize!=0 && map instanceof SortedMap) { 352 if (Objects.equals(comparator, ((SortedMap<?,?>)map).comparator())) { 353 ++modCount; 354 try { 355 buildFromSorted(mapSize, map.entrySet().iterator(), 356 null, null); 357 } catch (java.io.IOException | ClassNotFoundException cannotHappen) { 358 } 359 return; 360 } 361 } 362 super.putAll(map); 363 } 364 365 /** 366 * Returns this map's entry for the given key, or {@code null} if the map 367 * does not contain an entry for the key. 368 * 369 * @return this map's entry for the given key, or {@code null} if the map 370 * does not contain an entry for the key 371 * @throws ClassCastException if the specified key cannot be compared 372 * with the keys currently in the map 373 * @throws NullPointerException if the specified key is null 374 * and this map uses natural ordering, or its comparator 375 * does not permit null keys 376 */ getEntry(Object key)377 final TreeMapEntry<K,V> getEntry(Object key) { 378 // Offload comparator-based version for sake of performance 379 if (comparator != null) 380 return getEntryUsingComparator(key); 381 Objects.requireNonNull(key); 382 @SuppressWarnings("unchecked") 383 Comparable<? super K> k = (Comparable<? super K>) key; 384 TreeMapEntry<K,V> p = root; 385 while (p != null) { 386 int cmp = k.compareTo(p.key); 387 if (cmp < 0) 388 p = p.left; 389 else if (cmp > 0) 390 p = p.right; 391 else 392 return p; 393 } 394 return null; 395 } 396 397 /** 398 * Version of getEntry using comparator. Split off from getEntry 399 * for performance. (This is not worth doing for most methods, 400 * that are less dependent on comparator performance, but is 401 * worthwhile here.) 402 */ getEntryUsingComparator(Object key)403 final TreeMapEntry<K,V> getEntryUsingComparator(Object key) { 404 @SuppressWarnings("unchecked") 405 K k = (K) key; 406 Comparator<? super K> cpr = comparator; 407 if (cpr != null) { 408 TreeMapEntry<K,V> p = root; 409 while (p != null) { 410 int cmp = cpr.compare(k, p.key); 411 if (cmp < 0) 412 p = p.left; 413 else if (cmp > 0) 414 p = p.right; 415 else 416 return p; 417 } 418 } 419 return null; 420 } 421 422 /** 423 * Gets the entry corresponding to the specified key; if no such entry 424 * exists, returns the entry for the least key greater than the specified 425 * key; if no such entry exists (i.e., the greatest key in the Tree is less 426 * than the specified key), returns {@code null}. 427 */ getCeilingEntry(K key)428 final TreeMapEntry<K,V> getCeilingEntry(K key) { 429 TreeMapEntry<K,V> p = root; 430 while (p != null) { 431 int cmp = compare(key, p.key); 432 if (cmp < 0) { 433 if (p.left != null) 434 p = p.left; 435 else 436 return p; 437 } else if (cmp > 0) { 438 if (p.right != null) { 439 p = p.right; 440 } else { 441 TreeMapEntry<K,V> parent = p.parent; 442 TreeMapEntry<K,V> ch = p; 443 while (parent != null && ch == parent.right) { 444 ch = parent; 445 parent = parent.parent; 446 } 447 return parent; 448 } 449 } else 450 return p; 451 } 452 return null; 453 } 454 455 /** 456 * Gets the entry corresponding to the specified key; if no such entry 457 * exists, returns the entry for the greatest key less than the specified 458 * key; if no such entry exists (i.e., the least key in the Tree is greater 459 * than the specified key), returns {@code null}. 460 */ getFloorEntry(K key)461 final TreeMapEntry<K,V> getFloorEntry(K key) { 462 TreeMapEntry<K,V> p = root; 463 while (p != null) { 464 int cmp = compare(key, p.key); 465 if (cmp > 0) { 466 if (p.right != null) 467 p = p.right; 468 else 469 return p; 470 } else if (cmp < 0) { 471 if (p.left != null) { 472 p = p.left; 473 } else { 474 TreeMapEntry<K,V> parent = p.parent; 475 TreeMapEntry<K,V> ch = p; 476 while (parent != null && ch == parent.left) { 477 ch = parent; 478 parent = parent.parent; 479 } 480 return parent; 481 } 482 } else 483 return p; 484 485 } 486 return null; 487 } 488 489 /** 490 * Returns the entry for the least key greater than the specified key; if 491 * no such entry exists (i.e., the greatest key in the Tree is less than 492 * or equal to the specified key), returns {@code null}. 493 */ getHigherEntry(K key)494 final TreeMapEntry<K,V> getHigherEntry(K key) { 495 TreeMapEntry<K,V> p = root; 496 while (p != null) { 497 int cmp = compare(key, p.key); 498 if (cmp < 0) { 499 if (p.left != null) 500 p = p.left; 501 else 502 return p; 503 } else { 504 if (p.right != null) { 505 p = p.right; 506 } else { 507 TreeMapEntry<K,V> parent = p.parent; 508 TreeMapEntry<K,V> ch = p; 509 while (parent != null && ch == parent.right) { 510 ch = parent; 511 parent = parent.parent; 512 } 513 return parent; 514 } 515 } 516 } 517 return null; 518 } 519 520 /** 521 * Returns the entry for the greatest key less than the specified key; if 522 * no such entry exists (i.e., the least key in the Tree is greater than 523 * or equal to the specified key), returns {@code null}. 524 */ getLowerEntry(K key)525 final TreeMapEntry<K,V> getLowerEntry(K key) { 526 TreeMapEntry<K,V> p = root; 527 while (p != null) { 528 int cmp = compare(key, p.key); 529 if (cmp > 0) { 530 if (p.right != null) 531 p = p.right; 532 else 533 return p; 534 } else { 535 if (p.left != null) { 536 p = p.left; 537 } else { 538 TreeMapEntry<K,V> parent = p.parent; 539 TreeMapEntry<K,V> ch = p; 540 while (parent != null && ch == parent.left) { 541 ch = parent; 542 parent = parent.parent; 543 } 544 return parent; 545 } 546 } 547 } 548 return null; 549 } 550 551 /** 552 * Associates the specified value with the specified key in this map. 553 * If the map previously contained a mapping for the key, the old 554 * value is replaced. 555 * 556 * @param key key with which the specified value is to be associated 557 * @param value value to be associated with the specified key 558 * 559 * @return the previous value associated with {@code key}, or 560 * {@code null} if there was no mapping for {@code key}. 561 * (A {@code null} return can also indicate that the map 562 * previously associated {@code null} with {@code key}.) 563 * @throws ClassCastException if the specified key cannot be compared 564 * with the keys currently in the map 565 * @throws NullPointerException if the specified key is null 566 * and this map uses natural ordering, or its comparator 567 * does not permit null keys 568 */ put(K key, V value)569 public V put(K key, V value) { 570 return put(key, value, true); 571 } 572 573 @Override putIfAbsent(K key, V value)574 public V putIfAbsent(K key, V value) { 575 return put(key, value, false); 576 } 577 578 /** 579 * {@inheritDoc} 580 * 581 * <p>This method will, on a best-effort basis, throw a 582 * {@link ConcurrentModificationException} if it is detected that the 583 * mapping function modifies this map during computation. 584 * 585 * @throws ConcurrentModificationException if it is detected that the 586 * mapping function modified this map 587 */ 588 @Override computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)589 public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { 590 Objects.requireNonNull(mappingFunction); 591 V newValue; 592 TreeMapEntry<K,V> t = root; 593 if (t == null) { 594 newValue = callMappingFunctionWithCheck(key, mappingFunction); 595 if (newValue != null) { 596 addEntryToEmptyMap(key, newValue); 597 return newValue; 598 } else { 599 return null; 600 } 601 } 602 int cmp; 603 TreeMapEntry<K,V> parent; 604 // split comparator and comparable paths 605 Comparator<? super K> cpr = comparator; 606 if (cpr != null) { 607 do { 608 parent = t; 609 cmp = cpr.compare(key, t.key); 610 if (cmp < 0) 611 t = t.left; 612 else if (cmp > 0) 613 t = t.right; 614 else { 615 if (t.value == null) { 616 t.value = callMappingFunctionWithCheck(key, mappingFunction); 617 } 618 return t.value; 619 } 620 } while (t != null); 621 } else { 622 Objects.requireNonNull(key); 623 @SuppressWarnings("unchecked") 624 Comparable<? super K> k = (Comparable<? super K>) key; 625 do { 626 parent = t; 627 cmp = k.compareTo(t.key); 628 if (cmp < 0) 629 t = t.left; 630 else if (cmp > 0) 631 t = t.right; 632 else { 633 if (t.value == null) { 634 t.value = callMappingFunctionWithCheck(key, mappingFunction); 635 } 636 return t.value; 637 } 638 } while (t != null); 639 } 640 newValue = callMappingFunctionWithCheck(key, mappingFunction); 641 if (newValue != null) { 642 addEntry(key, newValue, parent, cmp < 0); 643 return newValue; 644 } 645 return null; 646 } 647 648 /** 649 * {@inheritDoc} 650 * 651 * <p>This method will, on a best-effort basis, throw a 652 * {@link ConcurrentModificationException} if it is detected that the 653 * remapping function modifies this map during computation. 654 * 655 * @throws ConcurrentModificationException if it is detected that the 656 * remapping function modified this map 657 */ 658 @Override computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)659 public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 660 Objects.requireNonNull(remappingFunction); 661 TreeMapEntry<K,V> oldEntry = getEntry(key); 662 if (oldEntry != null && oldEntry.value != null) { 663 return remapValue(oldEntry, key, remappingFunction); 664 } else { 665 return null; 666 } 667 } 668 669 /** 670 * {@inheritDoc} 671 * 672 * <p>This method will, on a best-effort basis, throw a 673 * {@link ConcurrentModificationException} if it is detected that the 674 * remapping function modifies this map during computation. 675 * 676 * @throws ConcurrentModificationException if it is detected that the 677 * remapping function modified this map 678 */ 679 @Override compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)680 public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 681 Objects.requireNonNull(remappingFunction); 682 V newValue; 683 TreeMapEntry<K,V> t = root; 684 if (t == null) { 685 newValue = callRemappingFunctionWithCheck(key, null, remappingFunction); 686 if (newValue != null) { 687 addEntryToEmptyMap(key, newValue); 688 return newValue; 689 } else { 690 return null; 691 } 692 } 693 int cmp; 694 TreeMapEntry<K,V> parent; 695 // split comparator and comparable paths 696 Comparator<? super K> cpr = comparator; 697 if (cpr != null) { 698 do { 699 parent = t; 700 cmp = cpr.compare(key, t.key); 701 if (cmp < 0) 702 t = t.left; 703 else if (cmp > 0) 704 t = t.right; 705 else 706 return remapValue(t, key, remappingFunction); 707 } while (t != null); 708 } else { 709 Objects.requireNonNull(key); 710 @SuppressWarnings("unchecked") 711 Comparable<? super K> k = (Comparable<? super K>) key; 712 do { 713 parent = t; 714 cmp = k.compareTo(t.key); 715 if (cmp < 0) 716 t = t.left; 717 else if (cmp > 0) 718 t = t.right; 719 else 720 return remapValue(t, key, remappingFunction); 721 } while (t != null); 722 } 723 newValue = callRemappingFunctionWithCheck(key, null, remappingFunction); 724 if (newValue != null) { 725 addEntry(key, newValue, parent, cmp < 0); 726 return newValue; 727 } 728 return null; 729 } 730 731 /** 732 * {@inheritDoc} 733 * 734 * <p>This method will, on a best-effort basis, throw a 735 * {@link ConcurrentModificationException} if it is detected that the 736 * remapping function modifies this map during computation. 737 * 738 * @throws ConcurrentModificationException if it is detected that the 739 * remapping function modified this map 740 */ 741 @Override merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)742 public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { 743 Objects.requireNonNull(remappingFunction); 744 Objects.requireNonNull(value); 745 TreeMapEntry<K,V> t = root; 746 if (t == null) { 747 addEntryToEmptyMap(key, value); 748 return value; 749 } 750 int cmp; 751 TreeMapEntry<K,V> parent; 752 // split comparator and comparable paths 753 Comparator<? super K> cpr = comparator; 754 if (cpr != null) { 755 do { 756 parent = t; 757 cmp = cpr.compare(key, t.key); 758 if (cmp < 0) 759 t = t.left; 760 else if (cmp > 0) 761 t = t.right; 762 else return mergeValue(t, value, remappingFunction); 763 } while (t != null); 764 } else { 765 Objects.requireNonNull(key); 766 @SuppressWarnings("unchecked") 767 Comparable<? super K> k = (Comparable<? super K>) key; 768 do { 769 parent = t; 770 cmp = k.compareTo(t.key); 771 if (cmp < 0) 772 t = t.left; 773 else if (cmp > 0) 774 t = t.right; 775 else return mergeValue(t, value, remappingFunction); 776 } while (t != null); 777 } 778 addEntry(key, value, parent, cmp < 0); 779 return value; 780 } 781 callMappingFunctionWithCheck(K key, Function<? super K, ? extends V> mappingFunction)782 private V callMappingFunctionWithCheck(K key, Function<? super K, ? extends V> mappingFunction) { 783 int mc = modCount; 784 V newValue = mappingFunction.apply(key); 785 if (mc != modCount) { 786 throw new ConcurrentModificationException(); 787 } 788 return newValue; 789 } 790 callRemappingFunctionWithCheck(K key, V oldValue, BiFunction<? super K, ? super V, ? extends V> remappingFunction)791 private V callRemappingFunctionWithCheck(K key, V oldValue, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 792 int mc = modCount; 793 V newValue = remappingFunction.apply(key, oldValue); 794 if (mc != modCount) { 795 throw new ConcurrentModificationException(); 796 } 797 return newValue; 798 } 799 addEntry(K key, V value, TreeMapEntry<K, V> parent, boolean addToLeft)800 private void addEntry(K key, V value, TreeMapEntry<K, V> parent, boolean addToLeft) { 801 TreeMapEntry<K,V> e = new TreeMapEntry<>(key, value, parent); 802 if (addToLeft) 803 parent.left = e; 804 else 805 parent.right = e; 806 fixAfterInsertion(e); 807 size++; 808 modCount++; 809 } 810 addEntryToEmptyMap(K key, V value)811 private void addEntryToEmptyMap(K key, V value) { 812 compare(key, key); // type (and possibly null) check 813 root = new TreeMapEntry<>(key, value, null); 814 size = 1; 815 modCount++; 816 } 817 put(K key, V value, boolean replaceOld)818 private V put(K key, V value, boolean replaceOld) { 819 TreeMapEntry<K,V> t = root; 820 if (t == null) { 821 addEntryToEmptyMap(key, value); 822 return null; 823 } 824 int cmp; 825 TreeMapEntry<K,V> parent; 826 // split comparator and comparable paths 827 Comparator<? super K> cpr = comparator; 828 if (cpr != null) { 829 do { 830 parent = t; 831 cmp = cpr.compare(key, t.key); 832 if (cmp < 0) 833 t = t.left; 834 else if (cmp > 0) 835 t = t.right; 836 else { 837 V oldValue = t.value; 838 if (replaceOld || oldValue == null) { 839 t.value = value; 840 } 841 return oldValue; 842 } 843 } while (t != null); 844 } else { 845 Objects.requireNonNull(key); 846 @SuppressWarnings("unchecked") 847 Comparable<? super K> k = (Comparable<? super K>) key; 848 do { 849 parent = t; 850 cmp = k.compareTo(t.key); 851 if (cmp < 0) 852 t = t.left; 853 else if (cmp > 0) 854 t = t.right; 855 else { 856 V oldValue = t.value; 857 if (replaceOld || oldValue == null) { 858 t.value = value; 859 } 860 return oldValue; 861 } 862 } while (t != null); 863 } 864 addEntry(key, value, parent, cmp < 0); 865 return null; 866 } 867 remapValue(TreeMapEntry<K,V> t, K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)868 private V remapValue(TreeMapEntry<K,V> t, K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 869 V newValue = callRemappingFunctionWithCheck(key, t.value, remappingFunction); 870 if (newValue == null) { 871 deleteEntry(t); 872 return null; 873 } else { 874 // replace old mapping 875 t.value = newValue; 876 return newValue; 877 } 878 } 879 mergeValue(TreeMapEntry<K,V> t, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)880 private V mergeValue(TreeMapEntry<K,V> t, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { 881 V oldValue = t.value; 882 V newValue; 883 if (t.value == null) { 884 newValue = value; 885 } else { 886 int mc = modCount; 887 newValue = remappingFunction.apply(oldValue, value); 888 if (mc != modCount) { 889 throw new ConcurrentModificationException(); 890 } 891 } 892 if (newValue == null) { 893 deleteEntry(t); 894 return null; 895 } else { 896 // replace old mapping 897 t.value = newValue; 898 return newValue; 899 } 900 } 901 902 /** 903 * Removes the mapping for this key from this TreeMap if present. 904 * 905 * @param key key for which mapping should be removed 906 * @return the previous value associated with {@code key}, or 907 * {@code null} if there was no mapping for {@code key}. 908 * (A {@code null} return can also indicate that the map 909 * previously associated {@code null} with {@code key}.) 910 * @throws ClassCastException if the specified key cannot be compared 911 * with the keys currently in the map 912 * @throws NullPointerException if the specified key is null 913 * and this map uses natural ordering, or its comparator 914 * does not permit null keys 915 */ remove(Object key)916 public V remove(Object key) { 917 TreeMapEntry<K,V> p = getEntry(key); 918 if (p == null) 919 return null; 920 921 V oldValue = p.value; 922 deleteEntry(p); 923 return oldValue; 924 } 925 926 /** 927 * Removes all of the mappings from this map. 928 * The map will be empty after this call returns. 929 */ clear()930 public void clear() { 931 modCount++; 932 size = 0; 933 root = null; 934 } 935 936 /** 937 * Returns a shallow copy of this {@code TreeMap} instance. (The keys and 938 * values themselves are not cloned.) 939 * 940 * @return a shallow copy of this map 941 */ clone()942 public Object clone() { 943 TreeMap<?,?> clone; 944 try { 945 clone = (TreeMap<?,?>) super.clone(); 946 } catch (CloneNotSupportedException e) { 947 throw new InternalError(e); 948 } 949 950 // Put clone into "virgin" state (except for comparator) 951 clone.root = null; 952 clone.size = 0; 953 clone.modCount = 0; 954 clone.entrySet = null; 955 clone.navigableKeySet = null; 956 clone.descendingMap = null; 957 958 // Initialize clone with our mappings 959 try { 960 clone.buildFromSorted(size, entrySet().iterator(), null, null); 961 } catch (java.io.IOException | ClassNotFoundException cannotHappen) { 962 } 963 964 return clone; 965 } 966 967 // NavigableMap API methods 968 969 /** 970 * @since 1.6 971 */ firstEntry()972 public Map.Entry<K,V> firstEntry() { 973 return exportEntry(getFirstEntry()); 974 } 975 976 /** 977 * @since 1.6 978 */ lastEntry()979 public Map.Entry<K,V> lastEntry() { 980 return exportEntry(getLastEntry()); 981 } 982 983 /** 984 * @since 1.6 985 */ pollFirstEntry()986 public Map.Entry<K,V> pollFirstEntry() { 987 TreeMapEntry<K,V> p = getFirstEntry(); 988 Map.Entry<K,V> result = exportEntry(p); 989 if (p != null) 990 deleteEntry(p); 991 return result; 992 } 993 994 /** 995 * @since 1.6 996 */ pollLastEntry()997 public Map.Entry<K,V> pollLastEntry() { 998 TreeMapEntry<K,V> p = getLastEntry(); 999 Map.Entry<K,V> result = exportEntry(p); 1000 if (p != null) 1001 deleteEntry(p); 1002 return result; 1003 } 1004 1005 /** 1006 * @throws ClassCastException {@inheritDoc} 1007 * @throws NullPointerException if the specified key is null 1008 * and this map uses natural ordering, or its comparator 1009 * does not permit null keys 1010 * @since 1.6 1011 */ lowerEntry(K key)1012 public Map.Entry<K,V> lowerEntry(K key) { 1013 return exportEntry(getLowerEntry(key)); 1014 } 1015 1016 /** 1017 * @throws ClassCastException {@inheritDoc} 1018 * @throws NullPointerException if the specified key is null 1019 * and this map uses natural ordering, or its comparator 1020 * does not permit null keys 1021 * @since 1.6 1022 */ lowerKey(K key)1023 public K lowerKey(K key) { 1024 return keyOrNull(getLowerEntry(key)); 1025 } 1026 1027 /** 1028 * @throws ClassCastException {@inheritDoc} 1029 * @throws NullPointerException if the specified key is null 1030 * and this map uses natural ordering, or its comparator 1031 * does not permit null keys 1032 * @since 1.6 1033 */ floorEntry(K key)1034 public Map.Entry<K,V> floorEntry(K key) { 1035 return exportEntry(getFloorEntry(key)); 1036 } 1037 1038 /** 1039 * @throws ClassCastException {@inheritDoc} 1040 * @throws NullPointerException if the specified key is null 1041 * and this map uses natural ordering, or its comparator 1042 * does not permit null keys 1043 * @since 1.6 1044 */ floorKey(K key)1045 public K floorKey(K key) { 1046 return keyOrNull(getFloorEntry(key)); 1047 } 1048 1049 /** 1050 * @throws ClassCastException {@inheritDoc} 1051 * @throws NullPointerException if the specified key is null 1052 * and this map uses natural ordering, or its comparator 1053 * does not permit null keys 1054 * @since 1.6 1055 */ ceilingEntry(K key)1056 public Map.Entry<K,V> ceilingEntry(K key) { 1057 return exportEntry(getCeilingEntry(key)); 1058 } 1059 1060 /** 1061 * @throws ClassCastException {@inheritDoc} 1062 * @throws NullPointerException if the specified key is null 1063 * and this map uses natural ordering, or its comparator 1064 * does not permit null keys 1065 * @since 1.6 1066 */ ceilingKey(K key)1067 public K ceilingKey(K key) { 1068 return keyOrNull(getCeilingEntry(key)); 1069 } 1070 1071 /** 1072 * @throws ClassCastException {@inheritDoc} 1073 * @throws NullPointerException if the specified key is null 1074 * and this map uses natural ordering, or its comparator 1075 * does not permit null keys 1076 * @since 1.6 1077 */ higherEntry(K key)1078 public Map.Entry<K,V> higherEntry(K key) { 1079 return exportEntry(getHigherEntry(key)); 1080 } 1081 1082 /** 1083 * @throws ClassCastException {@inheritDoc} 1084 * @throws NullPointerException if the specified key is null 1085 * and this map uses natural ordering, or its comparator 1086 * does not permit null keys 1087 * @since 1.6 1088 */ higherKey(K key)1089 public K higherKey(K key) { 1090 return keyOrNull(getHigherEntry(key)); 1091 } 1092 1093 // Views 1094 1095 /** 1096 * Fields initialized to contain an instance of the entry set view 1097 * the first time this view is requested. Views are stateless, so 1098 * there's no reason to create more than one. 1099 */ 1100 private transient EntrySet entrySet; 1101 private transient KeySet<K> navigableKeySet; 1102 private transient NavigableMap<K,V> descendingMap; 1103 1104 /** 1105 * Returns a {@link Set} view of the keys contained in this map. 1106 * 1107 * <p>The set's iterator returns the keys in ascending order. 1108 * The set's spliterator is 1109 * <em><a href="Spliterator.html#binding">late-binding</a></em>, 1110 * <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED} 1111 * and {@link Spliterator#ORDERED} with an encounter order that is ascending 1112 * key order. The spliterator's comparator (see 1113 * {@link java.util.Spliterator#getComparator()}) is {@code null} if 1114 * the tree map's comparator (see {@link #comparator()}) is {@code null}. 1115 * Otherwise, the spliterator's comparator is the same as or imposes the 1116 * same total ordering as the tree map's comparator. 1117 * 1118 * <p>The set is backed by the map, so changes to the map are 1119 * reflected in the set, and vice-versa. If the map is modified 1120 * while an iteration over the set is in progress (except through 1121 * the iterator's own {@code remove} operation), the results of 1122 * the iteration are undefined. The set supports element removal, 1123 * which removes the corresponding mapping from the map, via the 1124 * {@code Iterator.remove}, {@code Set.remove}, 1125 * {@code removeAll}, {@code retainAll}, and {@code clear} 1126 * operations. It does not support the {@code add} or {@code addAll} 1127 * operations. 1128 */ keySet()1129 public Set<K> keySet() { 1130 return navigableKeySet(); 1131 } 1132 1133 /** 1134 * @since 1.6 1135 */ navigableKeySet()1136 public NavigableSet<K> navigableKeySet() { 1137 KeySet<K> nks = navigableKeySet; 1138 return (nks != null) ? nks : (navigableKeySet = new KeySet<>(this)); 1139 } 1140 1141 /** 1142 * @since 1.6 1143 */ descendingKeySet()1144 public NavigableSet<K> descendingKeySet() { 1145 return descendingMap().navigableKeySet(); 1146 } 1147 1148 /** 1149 * Returns a {@link Collection} view of the values contained in this map. 1150 * 1151 * <p>The collection's iterator returns the values in ascending order 1152 * of the corresponding keys. The collection's spliterator is 1153 * <em><a href="Spliterator.html#binding">late-binding</a></em>, 1154 * <em>fail-fast</em>, and additionally reports {@link Spliterator#ORDERED} 1155 * with an encounter order that is ascending order of the corresponding 1156 * keys. 1157 * 1158 * <p>The collection is backed by the map, so changes to the map are 1159 * reflected in the collection, and vice-versa. If the map is 1160 * modified while an iteration over the collection is in progress 1161 * (except through the iterator's own {@code remove} operation), 1162 * the results of the iteration are undefined. The collection 1163 * supports element removal, which removes the corresponding 1164 * mapping from the map, via the {@code Iterator.remove}, 1165 * {@code Collection.remove}, {@code removeAll}, 1166 * {@code retainAll} and {@code clear} operations. It does not 1167 * support the {@code add} or {@code addAll} operations. 1168 */ values()1169 public Collection<V> values() { 1170 Collection<V> vs = values; 1171 if (vs == null) { 1172 vs = new Values(); 1173 values = vs; 1174 } 1175 return vs; 1176 } 1177 1178 /** 1179 * Returns a {@link Set} view of the mappings contained in this map. 1180 * 1181 * <p>The set's iterator returns the entries in ascending key order. The 1182 * set's spliterator is 1183 * <em><a href="Spliterator.html#binding">late-binding</a></em>, 1184 * <em>fail-fast</em>, and additionally reports {@link Spliterator#SORTED} and 1185 * {@link Spliterator#ORDERED} with an encounter order that is ascending key 1186 * order. 1187 * 1188 * <p>The set is backed by the map, so changes to the map are 1189 * reflected in the set, and vice-versa. If the map is modified 1190 * while an iteration over the set is in progress (except through 1191 * the iterator's own {@code remove} operation, or through the 1192 * {@code setValue} operation on a map entry returned by the 1193 * iterator) the results of the iteration are undefined. The set 1194 * supports element removal, which removes the corresponding 1195 * mapping from the map, via the {@code Iterator.remove}, 1196 * {@code Set.remove}, {@code removeAll}, {@code retainAll} and 1197 * {@code clear} operations. It does not support the 1198 * {@code add} or {@code addAll} operations. 1199 */ entrySet()1200 public Set<Map.Entry<K,V>> entrySet() { 1201 EntrySet es = entrySet; 1202 return (es != null) ? es : (entrySet = new EntrySet()); 1203 } 1204 1205 /** 1206 * @since 1.6 1207 */ descendingMap()1208 public NavigableMap<K, V> descendingMap() { 1209 NavigableMap<K, V> km = descendingMap; 1210 return (km != null) ? km : 1211 (descendingMap = new DescendingSubMap<>(this, 1212 true, null, true, 1213 true, null, true)); 1214 } 1215 1216 /** 1217 * @throws ClassCastException {@inheritDoc} 1218 * @throws NullPointerException if {@code fromKey} or {@code toKey} is 1219 * null and this map uses natural ordering, or its comparator 1220 * does not permit null keys 1221 * @throws IllegalArgumentException {@inheritDoc} 1222 * @since 1.6 1223 */ subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)1224 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, 1225 K toKey, boolean toInclusive) { 1226 return new AscendingSubMap<>(this, 1227 false, fromKey, fromInclusive, 1228 false, toKey, toInclusive); 1229 } 1230 1231 /** 1232 * @throws ClassCastException {@inheritDoc} 1233 * @throws NullPointerException if {@code toKey} is null 1234 * and this map uses natural ordering, or its comparator 1235 * does not permit null keys 1236 * @throws IllegalArgumentException {@inheritDoc} 1237 * @since 1.6 1238 */ headMap(K toKey, boolean inclusive)1239 public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { 1240 return new AscendingSubMap<>(this, 1241 true, null, true, 1242 false, toKey, inclusive); 1243 } 1244 1245 /** 1246 * @throws ClassCastException {@inheritDoc} 1247 * @throws NullPointerException if {@code fromKey} is null 1248 * and this map uses natural ordering, or its comparator 1249 * does not permit null keys 1250 * @throws IllegalArgumentException {@inheritDoc} 1251 * @since 1.6 1252 */ tailMap(K fromKey, boolean inclusive)1253 public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { 1254 return new AscendingSubMap<>(this, 1255 false, fromKey, inclusive, 1256 true, null, true); 1257 } 1258 1259 /** 1260 * @throws ClassCastException {@inheritDoc} 1261 * @throws NullPointerException if {@code fromKey} or {@code toKey} is 1262 * null and this map uses natural ordering, or its comparator 1263 * does not permit null keys 1264 * @throws IllegalArgumentException {@inheritDoc} 1265 */ subMap(K fromKey, K toKey)1266 public SortedMap<K,V> subMap(K fromKey, K toKey) { 1267 return subMap(fromKey, true, toKey, false); 1268 } 1269 1270 /** 1271 * @throws ClassCastException {@inheritDoc} 1272 * @throws NullPointerException if {@code toKey} is null 1273 * and this map uses natural ordering, or its comparator 1274 * does not permit null keys 1275 * @throws IllegalArgumentException {@inheritDoc} 1276 */ headMap(K toKey)1277 public SortedMap<K,V> headMap(K toKey) { 1278 return headMap(toKey, false); 1279 } 1280 1281 /** 1282 * @throws ClassCastException {@inheritDoc} 1283 * @throws NullPointerException if {@code fromKey} is null 1284 * and this map uses natural ordering, or its comparator 1285 * does not permit null keys 1286 * @throws IllegalArgumentException {@inheritDoc} 1287 */ tailMap(K fromKey)1288 public SortedMap<K,V> tailMap(K fromKey) { 1289 return tailMap(fromKey, true); 1290 } 1291 1292 @Override replace(K key, V oldValue, V newValue)1293 public boolean replace(K key, V oldValue, V newValue) { 1294 TreeMapEntry<K,V> p = getEntry(key); 1295 if (p!=null && Objects.equals(oldValue, p.value)) { 1296 p.value = newValue; 1297 return true; 1298 } 1299 return false; 1300 } 1301 1302 @Override replace(K key, V value)1303 public V replace(K key, V value) { 1304 TreeMapEntry<K,V> p = getEntry(key); 1305 if (p!=null) { 1306 V oldValue = p.value; 1307 p.value = value; 1308 return oldValue; 1309 } 1310 return null; 1311 } 1312 1313 @Override forEach(BiConsumer<? super K, ? super V> action)1314 public void forEach(BiConsumer<? super K, ? super V> action) { 1315 Objects.requireNonNull(action); 1316 int expectedModCount = modCount; 1317 for (TreeMapEntry<K, V> e = getFirstEntry(); e != null; e = successor(e)) { 1318 action.accept(e.key, e.value); 1319 1320 if (expectedModCount != modCount) { 1321 throw new ConcurrentModificationException(); 1322 } 1323 } 1324 } 1325 1326 @Override replaceAll(BiFunction<? super K, ? super V, ? extends V> function)1327 public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { 1328 Objects.requireNonNull(function); 1329 int expectedModCount = modCount; 1330 1331 for (TreeMapEntry<K, V> e = getFirstEntry(); e != null; e = successor(e)) { 1332 e.value = function.apply(e.key, e.value); 1333 1334 if (expectedModCount != modCount) { 1335 throw new ConcurrentModificationException(); 1336 } 1337 } 1338 } 1339 1340 // View class support 1341 1342 class Values extends AbstractCollection<V> { iterator()1343 public Iterator<V> iterator() { 1344 return new ValueIterator(getFirstEntry()); 1345 } 1346 size()1347 public int size() { 1348 return TreeMap.this.size(); 1349 } 1350 contains(Object o)1351 public boolean contains(Object o) { 1352 return TreeMap.this.containsValue(o); 1353 } 1354 remove(Object o)1355 public boolean remove(Object o) { 1356 for (TreeMapEntry<K,V> e = getFirstEntry(); e != null; e = successor(e)) { 1357 if (valEquals(e.getValue(), o)) { 1358 deleteEntry(e); 1359 return true; 1360 } 1361 } 1362 return false; 1363 } 1364 clear()1365 public void clear() { 1366 TreeMap.this.clear(); 1367 } 1368 spliterator()1369 public Spliterator<V> spliterator() { 1370 return new ValueSpliterator<>(TreeMap.this, null, null, 0, -1, 0); 1371 } 1372 } 1373 1374 class EntrySet extends AbstractSet<Map.Entry<K,V>> { iterator()1375 public Iterator<Map.Entry<K,V>> iterator() { 1376 return new EntryIterator(getFirstEntry()); 1377 } 1378 contains(Object o)1379 public boolean contains(Object o) { 1380 if (!(o instanceof Map.Entry<?, ?> entry)) 1381 return false; 1382 Object value = entry.getValue(); 1383 TreeMapEntry<K,V> p = getEntry(entry.getKey()); 1384 return p != null && valEquals(p.getValue(), value); 1385 } 1386 remove(Object o)1387 public boolean remove(Object o) { 1388 if (!(o instanceof Map.Entry<?, ?> entry)) 1389 return false; 1390 Object value = entry.getValue(); 1391 TreeMapEntry<K,V> p = getEntry(entry.getKey()); 1392 if (p != null && valEquals(p.getValue(), value)) { 1393 deleteEntry(p); 1394 return true; 1395 } 1396 return false; 1397 } 1398 size()1399 public int size() { 1400 return TreeMap.this.size(); 1401 } 1402 clear()1403 public void clear() { 1404 TreeMap.this.clear(); 1405 } 1406 spliterator()1407 public Spliterator<Map.Entry<K,V>> spliterator() { 1408 return new EntrySpliterator<>(TreeMap.this, null, null, 0, -1, 0); 1409 } 1410 } 1411 1412 /* 1413 * Unlike Values and EntrySet, the KeySet class is static, 1414 * delegating to a NavigableMap to allow use by SubMaps, which 1415 * outweighs the ugliness of needing type-tests for the following 1416 * Iterator methods that are defined appropriately in main versus 1417 * submap classes. 1418 */ 1419 keyIterator()1420 Iterator<K> keyIterator() { 1421 return new KeyIterator(getFirstEntry()); 1422 } 1423 descendingKeyIterator()1424 Iterator<K> descendingKeyIterator() { 1425 return new DescendingKeyIterator(getLastEntry()); 1426 } 1427 1428 static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> { 1429 private final NavigableMap<E, ?> m; KeySet(NavigableMap<E,?> map)1430 KeySet(NavigableMap<E,?> map) { m = map; } 1431 iterator()1432 public Iterator<E> iterator() { 1433 if (m instanceof TreeMap) 1434 return ((TreeMap<E,?>)m).keyIterator(); 1435 else 1436 return ((TreeMap.NavigableSubMap<E,?>)m).keyIterator(); 1437 } 1438 descendingIterator()1439 public Iterator<E> descendingIterator() { 1440 if (m instanceof TreeMap) 1441 return ((TreeMap<E,?>)m).descendingKeyIterator(); 1442 else 1443 return ((TreeMap.NavigableSubMap<E,?>)m).descendingKeyIterator(); 1444 } 1445 size()1446 public int size() { return m.size(); } isEmpty()1447 public boolean isEmpty() { return m.isEmpty(); } contains(Object o)1448 public boolean contains(Object o) { return m.containsKey(o); } clear()1449 public void clear() { m.clear(); } lower(E e)1450 public E lower(E e) { return m.lowerKey(e); } floor(E e)1451 public E floor(E e) { return m.floorKey(e); } ceiling(E e)1452 public E ceiling(E e) { return m.ceilingKey(e); } higher(E e)1453 public E higher(E e) { return m.higherKey(e); } first()1454 public E first() { return m.firstKey(); } last()1455 public E last() { return m.lastKey(); } comparator()1456 public Comparator<? super E> comparator() { return m.comparator(); } pollFirst()1457 public E pollFirst() { 1458 Map.Entry<E,?> e = m.pollFirstEntry(); 1459 return (e == null) ? null : e.getKey(); 1460 } pollLast()1461 public E pollLast() { 1462 Map.Entry<E,?> e = m.pollLastEntry(); 1463 return (e == null) ? null : e.getKey(); 1464 } remove(Object o)1465 public boolean remove(Object o) { 1466 int oldSize = size(); 1467 m.remove(o); 1468 return size() != oldSize; 1469 } subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)1470 public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, 1471 E toElement, boolean toInclusive) { 1472 return new KeySet<>(m.subMap(fromElement, fromInclusive, 1473 toElement, toInclusive)); 1474 } headSet(E toElement, boolean inclusive)1475 public NavigableSet<E> headSet(E toElement, boolean inclusive) { 1476 return new KeySet<>(m.headMap(toElement, inclusive)); 1477 } tailSet(E fromElement, boolean inclusive)1478 public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { 1479 return new KeySet<>(m.tailMap(fromElement, inclusive)); 1480 } subSet(E fromElement, E toElement)1481 public SortedSet<E> subSet(E fromElement, E toElement) { 1482 return subSet(fromElement, true, toElement, false); 1483 } headSet(E toElement)1484 public SortedSet<E> headSet(E toElement) { 1485 return headSet(toElement, false); 1486 } tailSet(E fromElement)1487 public SortedSet<E> tailSet(E fromElement) { 1488 return tailSet(fromElement, true); 1489 } descendingSet()1490 public NavigableSet<E> descendingSet() { 1491 return new KeySet<>(m.descendingMap()); 1492 } 1493 spliterator()1494 public Spliterator<E> spliterator() { 1495 return keySpliteratorFor(m); 1496 } 1497 } 1498 1499 /** 1500 * Base class for TreeMap Iterators 1501 */ 1502 abstract class PrivateEntryIterator<T> implements Iterator<T> { 1503 TreeMapEntry<K,V> next; 1504 TreeMapEntry<K,V> lastReturned; 1505 int expectedModCount; 1506 PrivateEntryIterator(TreeMapEntry<K,V> first)1507 PrivateEntryIterator(TreeMapEntry<K,V> first) { 1508 expectedModCount = modCount; 1509 lastReturned = null; 1510 next = first; 1511 } 1512 hasNext()1513 public final boolean hasNext() { 1514 return next != null; 1515 } 1516 nextEntry()1517 final TreeMapEntry<K,V> nextEntry() { 1518 TreeMapEntry<K,V> e = next; 1519 if (e == null) 1520 throw new NoSuchElementException(); 1521 if (modCount != expectedModCount) 1522 throw new ConcurrentModificationException(); 1523 next = successor(e); 1524 lastReturned = e; 1525 return e; 1526 } 1527 prevEntry()1528 final TreeMapEntry<K,V> prevEntry() { 1529 TreeMapEntry<K,V> e = next; 1530 if (e == null) 1531 throw new NoSuchElementException(); 1532 if (modCount != expectedModCount) 1533 throw new ConcurrentModificationException(); 1534 next = predecessor(e); 1535 lastReturned = e; 1536 return e; 1537 } 1538 remove()1539 public void remove() { 1540 if (lastReturned == null) 1541 throw new IllegalStateException(); 1542 if (modCount != expectedModCount) 1543 throw new ConcurrentModificationException(); 1544 // deleted entries are replaced by their successors 1545 if (lastReturned.left != null && lastReturned.right != null) 1546 next = lastReturned; 1547 deleteEntry(lastReturned); 1548 expectedModCount = modCount; 1549 lastReturned = null; 1550 } 1551 } 1552 1553 final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> { EntryIterator(TreeMapEntry<K,V> first)1554 EntryIterator(TreeMapEntry<K,V> first) { 1555 super(first); 1556 } next()1557 public Map.Entry<K,V> next() { 1558 return nextEntry(); 1559 } 1560 } 1561 1562 final class ValueIterator extends PrivateEntryIterator<V> { ValueIterator(TreeMapEntry<K,V> first)1563 ValueIterator(TreeMapEntry<K,V> first) { 1564 super(first); 1565 } next()1566 public V next() { 1567 return nextEntry().value; 1568 } 1569 } 1570 1571 final class KeyIterator extends PrivateEntryIterator<K> { KeyIterator(TreeMapEntry<K,V> first)1572 KeyIterator(TreeMapEntry<K,V> first) { 1573 super(first); 1574 } next()1575 public K next() { 1576 return nextEntry().key; 1577 } 1578 } 1579 1580 final class DescendingKeyIterator extends PrivateEntryIterator<K> { DescendingKeyIterator(TreeMapEntry<K,V> first)1581 DescendingKeyIterator(TreeMapEntry<K,V> first) { 1582 super(first); 1583 } next()1584 public K next() { 1585 return prevEntry().key; 1586 } remove()1587 public void remove() { 1588 if (lastReturned == null) 1589 throw new IllegalStateException(); 1590 if (modCount != expectedModCount) 1591 throw new ConcurrentModificationException(); 1592 deleteEntry(lastReturned); 1593 lastReturned = null; 1594 expectedModCount = modCount; 1595 } 1596 } 1597 1598 // Little utilities 1599 1600 /** 1601 * Compares two keys using the correct comparison method for this TreeMap. 1602 */ 1603 @SuppressWarnings("unchecked") compare(Object k1, Object k2)1604 final int compare(Object k1, Object k2) { 1605 return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2) 1606 : comparator.compare((K)k1, (K)k2); 1607 } 1608 1609 /** 1610 * Test two values for equality. Differs from o1.equals(o2) only in 1611 * that it copes with {@code null} o1 properly. 1612 */ valEquals(Object o1, Object o2)1613 static final boolean valEquals(Object o1, Object o2) { 1614 return (o1==null ? o2==null : o1.equals(o2)); 1615 } 1616 1617 /** 1618 * Return SimpleImmutableEntry for entry, or null if null 1619 */ exportEntry(TreeMapEntry<K,V> e)1620 static <K,V> Map.Entry<K,V> exportEntry(TreeMapEntry<K,V> e) { 1621 return (e == null) ? null : 1622 new AbstractMap.SimpleImmutableEntry<>(e); 1623 } 1624 1625 /** 1626 * Return key for entry, or null if null 1627 */ keyOrNull(TreeMapEntry<K,V> e)1628 static <K,V> K keyOrNull(TreeMapEntry<K,V> e) { 1629 return (e == null) ? null : e.key; 1630 } 1631 1632 /** 1633 * Returns the key corresponding to the specified Entry. 1634 * @throws NoSuchElementException if the Entry is null 1635 */ key(TreeMapEntry<K,?> e)1636 static <K> K key(TreeMapEntry<K,?> e) { 1637 if (e==null) 1638 throw new NoSuchElementException(); 1639 return e.key; 1640 } 1641 1642 1643 // SubMaps 1644 1645 /** 1646 * Dummy value serving as unmatchable fence key for unbounded 1647 * SubMapIterators 1648 */ 1649 private static final Object UNBOUNDED = new Object(); 1650 1651 /** 1652 * @serial include 1653 */ 1654 abstract static class NavigableSubMap<K,V> extends AbstractMap<K,V> 1655 implements NavigableMap<K,V>, java.io.Serializable { 1656 // Android-changed: Explicitly add a serialVersionUID so that we're serialization. 1657 // compatible with the Java-7 version of this class. Several new methods were added 1658 // in Java-8 but none of them have any bearing on the serialized format of the class 1659 // or require any additional state to be preserved. 1660 @java.io.Serial 1661 private static final long serialVersionUID = 2765629423043303731L; 1662 1663 /** 1664 * The backing map. 1665 */ 1666 final TreeMap<K,V> m; 1667 1668 /** 1669 * Endpoints are represented as triples (fromStart, lo, 1670 * loInclusive) and (toEnd, hi, hiInclusive). If fromStart is 1671 * true, then the low (absolute) bound is the start of the 1672 * backing map, and the other values are ignored. Otherwise, 1673 * if loInclusive is true, lo is the inclusive bound, else lo 1674 * is the exclusive bound. Similarly for the upper bound. 1675 */ 1676 @SuppressWarnings("serial") // Conditionally serializable 1677 final K lo; 1678 @SuppressWarnings("serial") // Conditionally serializable 1679 final K hi; 1680 final boolean fromStart, toEnd; 1681 final boolean loInclusive, hiInclusive; 1682 NavigableSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive)1683 NavigableSubMap(TreeMap<K,V> m, 1684 boolean fromStart, K lo, boolean loInclusive, 1685 boolean toEnd, K hi, boolean hiInclusive) { 1686 if (!fromStart && !toEnd) { 1687 if (m.compare(lo, hi) > 0) 1688 throw new IllegalArgumentException("fromKey > toKey"); 1689 } else { 1690 if (!fromStart) // type check 1691 m.compare(lo, lo); 1692 if (!toEnd) 1693 m.compare(hi, hi); 1694 } 1695 1696 this.m = m; 1697 this.fromStart = fromStart; 1698 this.lo = lo; 1699 this.loInclusive = loInclusive; 1700 this.toEnd = toEnd; 1701 this.hi = hi; 1702 this.hiInclusive = hiInclusive; 1703 } 1704 1705 // internal utilities 1706 tooLow(Object key)1707 final boolean tooLow(Object key) { 1708 if (!fromStart) { 1709 int c = m.compare(key, lo); 1710 if (c < 0 || (c == 0 && !loInclusive)) 1711 return true; 1712 } 1713 return false; 1714 } 1715 tooHigh(Object key)1716 final boolean tooHigh(Object key) { 1717 if (!toEnd) { 1718 int c = m.compare(key, hi); 1719 if (c > 0 || (c == 0 && !hiInclusive)) 1720 return true; 1721 } 1722 return false; 1723 } 1724 inRange(Object key)1725 final boolean inRange(Object key) { 1726 return !tooLow(key) && !tooHigh(key); 1727 } 1728 inClosedRange(Object key)1729 final boolean inClosedRange(Object key) { 1730 return (fromStart || m.compare(key, lo) >= 0) 1731 && (toEnd || m.compare(hi, key) >= 0); 1732 } 1733 inRange(Object key, boolean inclusive)1734 final boolean inRange(Object key, boolean inclusive) { 1735 return inclusive ? inRange(key) : inClosedRange(key); 1736 } 1737 1738 /* 1739 * Absolute versions of relation operations. 1740 * Subclasses map to these using like-named "sub" 1741 * versions that invert senses for descending maps 1742 */ 1743 absLowest()1744 final TreeMapEntry<K,V> absLowest() { 1745 TreeMapEntry<K,V> e = 1746 (fromStart ? m.getFirstEntry() : 1747 (loInclusive ? m.getCeilingEntry(lo) : 1748 m.getHigherEntry(lo))); 1749 return (e == null || tooHigh(e.key)) ? null : e; 1750 } 1751 absHighest()1752 final TreeMapEntry<K,V> absHighest() { 1753 TreeMapEntry<K,V> e = 1754 (toEnd ? m.getLastEntry() : 1755 (hiInclusive ? m.getFloorEntry(hi) : 1756 m.getLowerEntry(hi))); 1757 return (e == null || tooLow(e.key)) ? null : e; 1758 } 1759 absCeiling(K key)1760 final TreeMapEntry<K,V> absCeiling(K key) { 1761 if (tooLow(key)) 1762 return absLowest(); 1763 TreeMapEntry<K,V> e = m.getCeilingEntry(key); 1764 return (e == null || tooHigh(e.key)) ? null : e; 1765 } 1766 absHigher(K key)1767 final TreeMapEntry<K,V> absHigher(K key) { 1768 if (tooLow(key)) 1769 return absLowest(); 1770 TreeMapEntry<K,V> e = m.getHigherEntry(key); 1771 return (e == null || tooHigh(e.key)) ? null : e; 1772 } 1773 absFloor(K key)1774 final TreeMapEntry<K,V> absFloor(K key) { 1775 if (tooHigh(key)) 1776 return absHighest(); 1777 TreeMapEntry<K,V> e = m.getFloorEntry(key); 1778 return (e == null || tooLow(e.key)) ? null : e; 1779 } 1780 absLower(K key)1781 final TreeMapEntry<K,V> absLower(K key) { 1782 if (tooHigh(key)) 1783 return absHighest(); 1784 TreeMapEntry<K,V> e = m.getLowerEntry(key); 1785 return (e == null || tooLow(e.key)) ? null : e; 1786 } 1787 1788 /** Returns the absolute high fence for ascending traversal */ absHighFence()1789 final TreeMapEntry<K,V> absHighFence() { 1790 return (toEnd ? null : (hiInclusive ? 1791 m.getHigherEntry(hi) : 1792 m.getCeilingEntry(hi))); 1793 } 1794 1795 /** Return the absolute low fence for descending traversal */ absLowFence()1796 final TreeMapEntry<K,V> absLowFence() { 1797 return (fromStart ? null : (loInclusive ? 1798 m.getLowerEntry(lo) : 1799 m.getFloorEntry(lo))); 1800 } 1801 1802 // Abstract methods defined in ascending vs descending classes 1803 // These relay to the appropriate absolute versions 1804 subLowest()1805 abstract TreeMapEntry<K,V> subLowest(); subHighest()1806 abstract TreeMapEntry<K,V> subHighest(); subCeiling(K key)1807 abstract TreeMapEntry<K,V> subCeiling(K key); subHigher(K key)1808 abstract TreeMapEntry<K,V> subHigher(K key); subFloor(K key)1809 abstract TreeMapEntry<K,V> subFloor(K key); subLower(K key)1810 abstract TreeMapEntry<K,V> subLower(K key); 1811 1812 /** Returns ascending iterator from the perspective of this submap */ keyIterator()1813 abstract Iterator<K> keyIterator(); 1814 keySpliterator()1815 abstract Spliterator<K> keySpliterator(); 1816 1817 /** Returns descending iterator from the perspective of this submap */ descendingKeyIterator()1818 abstract Iterator<K> descendingKeyIterator(); 1819 1820 // public methods 1821 isEmpty()1822 public boolean isEmpty() { 1823 return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty(); 1824 } 1825 size()1826 public int size() { 1827 return (fromStart && toEnd) ? m.size() : entrySet().size(); 1828 } 1829 containsKey(Object key)1830 public final boolean containsKey(Object key) { 1831 return inRange(key) && m.containsKey(key); 1832 } 1833 put(K key, V value)1834 public final V put(K key, V value) { 1835 if (!inRange(key)) 1836 throw new IllegalArgumentException("key out of range"); 1837 return m.put(key, value); 1838 } 1839 putIfAbsent(K key, V value)1840 public V putIfAbsent(K key, V value) { 1841 if (!inRange(key)) 1842 throw new IllegalArgumentException("key out of range"); 1843 return m.putIfAbsent(key, value); 1844 } 1845 merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)1846 public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) { 1847 if (!inRange(key)) 1848 throw new IllegalArgumentException("key out of range"); 1849 return m.merge(key, value, remappingFunction); 1850 } 1851 computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)1852 public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) { 1853 if (!inRange(key)) { 1854 // Do not throw if mapping function returns null 1855 // to preserve compatibility with default computeIfAbsent implementation 1856 if (mappingFunction.apply(key) == null) return null; 1857 throw new IllegalArgumentException("key out of range"); 1858 } 1859 return m.computeIfAbsent(key, mappingFunction); 1860 } 1861 compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)1862 public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 1863 if (!inRange(key)) { 1864 // Do not throw if remapping function returns null 1865 // to preserve compatibility with default computeIfAbsent implementation 1866 if (remappingFunction.apply(key, null) == null) return null; 1867 throw new IllegalArgumentException("key out of range"); 1868 } 1869 return m.compute(key, remappingFunction); 1870 } 1871 computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)1872 public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) { 1873 return !inRange(key) ? null : m.computeIfPresent(key, remappingFunction); 1874 } 1875 get(Object key)1876 public final V get(Object key) { 1877 return !inRange(key) ? null : m.get(key); 1878 } 1879 remove(Object key)1880 public final V remove(Object key) { 1881 return !inRange(key) ? null : m.remove(key); 1882 } 1883 ceilingEntry(K key)1884 public final Map.Entry<K,V> ceilingEntry(K key) { 1885 return exportEntry(subCeiling(key)); 1886 } 1887 ceilingKey(K key)1888 public final K ceilingKey(K key) { 1889 return keyOrNull(subCeiling(key)); 1890 } 1891 higherEntry(K key)1892 public final Map.Entry<K,V> higherEntry(K key) { 1893 return exportEntry(subHigher(key)); 1894 } 1895 higherKey(K key)1896 public final K higherKey(K key) { 1897 return keyOrNull(subHigher(key)); 1898 } 1899 floorEntry(K key)1900 public final Map.Entry<K,V> floorEntry(K key) { 1901 return exportEntry(subFloor(key)); 1902 } 1903 floorKey(K key)1904 public final K floorKey(K key) { 1905 return keyOrNull(subFloor(key)); 1906 } 1907 lowerEntry(K key)1908 public final Map.Entry<K,V> lowerEntry(K key) { 1909 return exportEntry(subLower(key)); 1910 } 1911 lowerKey(K key)1912 public final K lowerKey(K key) { 1913 return keyOrNull(subLower(key)); 1914 } 1915 firstKey()1916 public final K firstKey() { 1917 return key(subLowest()); 1918 } 1919 lastKey()1920 public final K lastKey() { 1921 return key(subHighest()); 1922 } 1923 firstEntry()1924 public final Map.Entry<K,V> firstEntry() { 1925 return exportEntry(subLowest()); 1926 } 1927 lastEntry()1928 public final Map.Entry<K,V> lastEntry() { 1929 return exportEntry(subHighest()); 1930 } 1931 pollFirstEntry()1932 public final Map.Entry<K,V> pollFirstEntry() { 1933 TreeMapEntry<K,V> e = subLowest(); 1934 Map.Entry<K,V> result = exportEntry(e); 1935 if (e != null) 1936 m.deleteEntry(e); 1937 return result; 1938 } 1939 pollLastEntry()1940 public final Map.Entry<K,V> pollLastEntry() { 1941 TreeMapEntry<K,V> e = subHighest(); 1942 Map.Entry<K,V> result = exportEntry(e); 1943 if (e != null) 1944 m.deleteEntry(e); 1945 return result; 1946 } 1947 1948 // Views 1949 transient NavigableMap<K,V> descendingMapView; 1950 transient EntrySetView entrySetView; 1951 transient KeySet<K> navigableKeySetView; 1952 navigableKeySet()1953 public final NavigableSet<K> navigableKeySet() { 1954 KeySet<K> nksv = navigableKeySetView; 1955 return (nksv != null) ? nksv : 1956 (navigableKeySetView = new TreeMap.KeySet<>(this)); 1957 } 1958 keySet()1959 public final Set<K> keySet() { 1960 return navigableKeySet(); 1961 } 1962 descendingKeySet()1963 public NavigableSet<K> descendingKeySet() { 1964 return descendingMap().navigableKeySet(); 1965 } 1966 subMap(K fromKey, K toKey)1967 public final SortedMap<K,V> subMap(K fromKey, K toKey) { 1968 return subMap(fromKey, true, toKey, false); 1969 } 1970 headMap(K toKey)1971 public final SortedMap<K,V> headMap(K toKey) { 1972 return headMap(toKey, false); 1973 } 1974 tailMap(K fromKey)1975 public final SortedMap<K,V> tailMap(K fromKey) { 1976 return tailMap(fromKey, true); 1977 } 1978 1979 // View classes 1980 1981 abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> { 1982 private transient int size = -1, sizeModCount; 1983 size()1984 public int size() { 1985 if (fromStart && toEnd) 1986 return m.size(); 1987 if (size == -1 || sizeModCount != m.modCount) { 1988 sizeModCount = m.modCount; 1989 size = 0; 1990 Iterator<?> i = iterator(); 1991 while (i.hasNext()) { 1992 size++; 1993 i.next(); 1994 } 1995 } 1996 return size; 1997 } 1998 isEmpty()1999 public boolean isEmpty() { 2000 TreeMapEntry<K,V> n = absLowest(); 2001 return n == null || tooHigh(n.key); 2002 } 2003 contains(Object o)2004 public boolean contains(Object o) { 2005 if (!(o instanceof Entry<?, ?> entry)) 2006 return false; 2007 Object key = entry.getKey(); 2008 if (!inRange(key)) 2009 return false; 2010 TreeMapEntry<?, ?> node = m.getEntry(key); 2011 return node != null && 2012 valEquals(node.getValue(), entry.getValue()); 2013 } 2014 remove(Object o)2015 public boolean remove(Object o) { 2016 if (!(o instanceof Entry<?, ?> entry)) 2017 return false; 2018 Object key = entry.getKey(); 2019 if (!inRange(key)) 2020 return false; 2021 TreeMapEntry<K,V> node = m.getEntry(key); 2022 if (node!=null && valEquals(node.getValue(), 2023 entry.getValue())) { 2024 m.deleteEntry(node); 2025 return true; 2026 } 2027 return false; 2028 } 2029 } 2030 2031 /** 2032 * Iterators for SubMaps 2033 */ 2034 abstract class SubMapIterator<T> implements Iterator<T> { 2035 TreeMapEntry<K,V> lastReturned; 2036 TreeMapEntry<K,V> next; 2037 final Object fenceKey; 2038 int expectedModCount; 2039 SubMapIterator(TreeMapEntry<K,V> first, TreeMapEntry<K,V> fence)2040 SubMapIterator(TreeMapEntry<K,V> first, 2041 TreeMapEntry<K,V> fence) { 2042 expectedModCount = m.modCount; 2043 lastReturned = null; 2044 next = first; 2045 fenceKey = fence == null ? UNBOUNDED : fence.key; 2046 } 2047 hasNext()2048 public final boolean hasNext() { 2049 return next != null && next.key != fenceKey; 2050 } 2051 nextEntry()2052 final TreeMapEntry<K,V> nextEntry() { 2053 TreeMapEntry<K,V> e = next; 2054 if (e == null || e.key == fenceKey) 2055 throw new NoSuchElementException(); 2056 if (m.modCount != expectedModCount) 2057 throw new ConcurrentModificationException(); 2058 next = successor(e); 2059 lastReturned = e; 2060 return e; 2061 } 2062 prevEntry()2063 final TreeMapEntry<K,V> prevEntry() { 2064 TreeMapEntry<K,V> e = next; 2065 if (e == null || e.key == fenceKey) 2066 throw new NoSuchElementException(); 2067 if (m.modCount != expectedModCount) 2068 throw new ConcurrentModificationException(); 2069 next = predecessor(e); 2070 lastReturned = e; 2071 return e; 2072 } 2073 removeAscending()2074 final void removeAscending() { 2075 if (lastReturned == null) 2076 throw new IllegalStateException(); 2077 if (m.modCount != expectedModCount) 2078 throw new ConcurrentModificationException(); 2079 // deleted entries are replaced by their successors 2080 if (lastReturned.left != null && lastReturned.right != null) 2081 next = lastReturned; 2082 m.deleteEntry(lastReturned); 2083 lastReturned = null; 2084 expectedModCount = m.modCount; 2085 } 2086 removeDescending()2087 final void removeDescending() { 2088 if (lastReturned == null) 2089 throw new IllegalStateException(); 2090 if (m.modCount != expectedModCount) 2091 throw new ConcurrentModificationException(); 2092 m.deleteEntry(lastReturned); 2093 lastReturned = null; 2094 expectedModCount = m.modCount; 2095 } 2096 2097 } 2098 2099 final class SubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { SubMapEntryIterator(TreeMapEntry<K,V> first, TreeMapEntry<K,V> fence)2100 SubMapEntryIterator(TreeMapEntry<K,V> first, 2101 TreeMapEntry<K,V> fence) { 2102 super(first, fence); 2103 } next()2104 public Map.Entry<K,V> next() { 2105 return nextEntry(); 2106 } remove()2107 public void remove() { 2108 removeAscending(); 2109 } 2110 } 2111 2112 final class DescendingSubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> { DescendingSubMapEntryIterator(TreeMapEntry<K,V> last, TreeMapEntry<K,V> fence)2113 DescendingSubMapEntryIterator(TreeMapEntry<K,V> last, 2114 TreeMapEntry<K,V> fence) { 2115 super(last, fence); 2116 } 2117 next()2118 public Map.Entry<K,V> next() { 2119 return prevEntry(); 2120 } remove()2121 public void remove() { 2122 removeDescending(); 2123 } 2124 } 2125 2126 // Implement minimal Spliterator as KeySpliterator backup 2127 final class SubMapKeyIterator extends SubMapIterator<K> 2128 implements Spliterator<K> { SubMapKeyIterator(TreeMapEntry<K,V> first, TreeMapEntry<K,V> fence)2129 SubMapKeyIterator(TreeMapEntry<K,V> first, 2130 TreeMapEntry<K,V> fence) { 2131 super(first, fence); 2132 } next()2133 public K next() { 2134 return nextEntry().key; 2135 } remove()2136 public void remove() { 2137 removeAscending(); 2138 } trySplit()2139 public Spliterator<K> trySplit() { 2140 return null; 2141 } forEachRemaining(Consumer<? super K> action)2142 public void forEachRemaining(Consumer<? super K> action) { 2143 while (hasNext()) 2144 action.accept(next()); 2145 } tryAdvance(Consumer<? super K> action)2146 public boolean tryAdvance(Consumer<? super K> action) { 2147 if (hasNext()) { 2148 action.accept(next()); 2149 return true; 2150 } 2151 return false; 2152 } estimateSize()2153 public long estimateSize() { 2154 return Long.MAX_VALUE; 2155 } characteristics()2156 public int characteristics() { 2157 return Spliterator.DISTINCT | Spliterator.ORDERED | 2158 Spliterator.SORTED; 2159 } getComparator()2160 public final Comparator<? super K> getComparator() { 2161 return NavigableSubMap.this.comparator(); 2162 } 2163 } 2164 2165 final class DescendingSubMapKeyIterator extends SubMapIterator<K> 2166 implements Spliterator<K> { DescendingSubMapKeyIterator(TreeMapEntry<K,V> last, TreeMapEntry<K,V> fence)2167 DescendingSubMapKeyIterator(TreeMapEntry<K,V> last, 2168 TreeMapEntry<K,V> fence) { 2169 super(last, fence); 2170 } next()2171 public K next() { 2172 return prevEntry().key; 2173 } remove()2174 public void remove() { 2175 removeDescending(); 2176 } trySplit()2177 public Spliterator<K> trySplit() { 2178 return null; 2179 } forEachRemaining(Consumer<? super K> action)2180 public void forEachRemaining(Consumer<? super K> action) { 2181 while (hasNext()) 2182 action.accept(next()); 2183 } tryAdvance(Consumer<? super K> action)2184 public boolean tryAdvance(Consumer<? super K> action) { 2185 if (hasNext()) { 2186 action.accept(next()); 2187 return true; 2188 } 2189 return false; 2190 } estimateSize()2191 public long estimateSize() { 2192 return Long.MAX_VALUE; 2193 } characteristics()2194 public int characteristics() { 2195 return Spliterator.DISTINCT | Spliterator.ORDERED; 2196 } 2197 } 2198 } 2199 2200 /** 2201 * @serial include 2202 */ 2203 static final class AscendingSubMap<K,V> extends NavigableSubMap<K,V> { 2204 @java.io.Serial 2205 private static final long serialVersionUID = 912986545866124060L; 2206 AscendingSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive)2207 AscendingSubMap(TreeMap<K,V> m, 2208 boolean fromStart, K lo, boolean loInclusive, 2209 boolean toEnd, K hi, boolean hiInclusive) { 2210 super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); 2211 } 2212 comparator()2213 public Comparator<? super K> comparator() { 2214 return m.comparator(); 2215 } 2216 subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)2217 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, 2218 K toKey, boolean toInclusive) { 2219 if (!inRange(fromKey, fromInclusive)) 2220 throw new IllegalArgumentException("fromKey out of range"); 2221 if (!inRange(toKey, toInclusive)) 2222 throw new IllegalArgumentException("toKey out of range"); 2223 return new AscendingSubMap<>(m, 2224 false, fromKey, fromInclusive, 2225 false, toKey, toInclusive); 2226 } 2227 headMap(K toKey, boolean inclusive)2228 public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { 2229 // BEGIN Android-changed: Fix for edge cases. 2230 // if (!inRange(toKey, inclusive)) 2231 if (!inRange(toKey) && !(!toEnd && m.compare(toKey, hi) == 0 && 2232 !hiInclusive && !inclusive)) 2233 // END Android-changed: Fix for edge cases. 2234 throw new IllegalArgumentException("toKey out of range"); 2235 return new AscendingSubMap<>(m, 2236 fromStart, lo, loInclusive, 2237 false, toKey, inclusive); 2238 } 2239 tailMap(K fromKey, boolean inclusive)2240 public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { 2241 // BEGIN Android-changed: Fix for edge cases. 2242 // if (!inRange(fromKey, inclusive)) 2243 if (!inRange(fromKey) && !(!fromStart && m.compare(fromKey, lo) == 0 && 2244 !loInclusive && !inclusive)) 2245 // END Android-changed: Fix for edge cases. 2246 throw new IllegalArgumentException("fromKey out of range"); 2247 return new AscendingSubMap<>(m, 2248 false, fromKey, inclusive, 2249 toEnd, hi, hiInclusive); 2250 } 2251 descendingMap()2252 public NavigableMap<K,V> descendingMap() { 2253 NavigableMap<K,V> mv = descendingMapView; 2254 return (mv != null) ? mv : 2255 (descendingMapView = 2256 new DescendingSubMap<>(m, 2257 fromStart, lo, loInclusive, 2258 toEnd, hi, hiInclusive)); 2259 } 2260 keyIterator()2261 Iterator<K> keyIterator() { 2262 return new SubMapKeyIterator(absLowest(), absHighFence()); 2263 } 2264 keySpliterator()2265 Spliterator<K> keySpliterator() { 2266 return new SubMapKeyIterator(absLowest(), absHighFence()); 2267 } 2268 descendingKeyIterator()2269 Iterator<K> descendingKeyIterator() { 2270 return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); 2271 } 2272 2273 final class AscendingEntrySetView extends EntrySetView { iterator()2274 public Iterator<Map.Entry<K,V>> iterator() { 2275 return new SubMapEntryIterator(absLowest(), absHighFence()); 2276 } 2277 } 2278 entrySet()2279 public Set<Map.Entry<K,V>> entrySet() { 2280 EntrySetView es = entrySetView; 2281 return (es != null) ? es : (entrySetView = new AscendingEntrySetView()); 2282 } 2283 subLowest()2284 TreeMapEntry<K,V> subLowest() { return absLowest(); } subHighest()2285 TreeMapEntry<K,V> subHighest() { return absHighest(); } subCeiling(K key)2286 TreeMapEntry<K,V> subCeiling(K key) { return absCeiling(key); } subHigher(K key)2287 TreeMapEntry<K,V> subHigher(K key) { return absHigher(key); } subFloor(K key)2288 TreeMapEntry<K,V> subFloor(K key) { return absFloor(key); } subLower(K key)2289 TreeMapEntry<K,V> subLower(K key) { return absLower(key); } 2290 } 2291 2292 /** 2293 * @serial include 2294 */ 2295 static final class DescendingSubMap<K,V> extends NavigableSubMap<K,V> { 2296 @java.io.Serial 2297 private static final long serialVersionUID = 912986545866120460L; DescendingSubMap(TreeMap<K,V> m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive)2298 DescendingSubMap(TreeMap<K,V> m, 2299 boolean fromStart, K lo, boolean loInclusive, 2300 boolean toEnd, K hi, boolean hiInclusive) { 2301 super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); 2302 } 2303 2304 @SuppressWarnings("serial") // Conditionally serializable 2305 private final Comparator<? super K> reverseComparator = 2306 Collections.reverseOrder(m.comparator); 2307 comparator()2308 public Comparator<? super K> comparator() { 2309 return reverseComparator; 2310 } 2311 subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)2312 public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, 2313 K toKey, boolean toInclusive) { 2314 if (!inRange(fromKey, fromInclusive)) 2315 throw new IllegalArgumentException("fromKey out of range"); 2316 if (!inRange(toKey, toInclusive)) 2317 throw new IllegalArgumentException("toKey out of range"); 2318 return new DescendingSubMap<>(m, 2319 false, toKey, toInclusive, 2320 false, fromKey, fromInclusive); 2321 } 2322 headMap(K toKey, boolean inclusive)2323 public NavigableMap<K,V> headMap(K toKey, boolean inclusive) { 2324 // BEGIN Android-changed: Fix for edge cases. 2325 // if (!inRange(toKey, inclusive)) 2326 if (!inRange(toKey) && !(!fromStart && m.compare(toKey, lo) == 0 && 2327 !loInclusive && !inclusive)) 2328 // END Android-changed: Fix for edge cases. 2329 throw new IllegalArgumentException("toKey out of range"); 2330 return new DescendingSubMap<>(m, 2331 false, toKey, inclusive, 2332 toEnd, hi, hiInclusive); 2333 } 2334 tailMap(K fromKey, boolean inclusive)2335 public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { 2336 // BEGIN Android-changed: Fix for edge cases. 2337 // if (!inRange(fromKey, inclusive)) 2338 if (!inRange(fromKey) && !(!toEnd && m.compare(fromKey, hi) == 0 && 2339 !hiInclusive && !inclusive)) 2340 // END Android-changed: Fix for edge cases. 2341 throw new IllegalArgumentException("fromKey out of range"); 2342 return new DescendingSubMap<>(m, 2343 fromStart, lo, loInclusive, 2344 false, fromKey, inclusive); 2345 } 2346 descendingMap()2347 public NavigableMap<K,V> descendingMap() { 2348 NavigableMap<K,V> mv = descendingMapView; 2349 return (mv != null) ? mv : 2350 (descendingMapView = 2351 new AscendingSubMap<>(m, 2352 fromStart, lo, loInclusive, 2353 toEnd, hi, hiInclusive)); 2354 } 2355 keyIterator()2356 Iterator<K> keyIterator() { 2357 return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); 2358 } 2359 keySpliterator()2360 Spliterator<K> keySpliterator() { 2361 return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); 2362 } 2363 descendingKeyIterator()2364 Iterator<K> descendingKeyIterator() { 2365 return new SubMapKeyIterator(absLowest(), absHighFence()); 2366 } 2367 2368 final class DescendingEntrySetView extends EntrySetView { iterator()2369 public Iterator<Map.Entry<K,V>> iterator() { 2370 return new DescendingSubMapEntryIterator(absHighest(), absLowFence()); 2371 } 2372 } 2373 entrySet()2374 public Set<Map.Entry<K,V>> entrySet() { 2375 EntrySetView es = entrySetView; 2376 return (es != null) ? es : (entrySetView = new DescendingEntrySetView()); 2377 } 2378 subLowest()2379 TreeMapEntry<K,V> subLowest() { return absHighest(); } subHighest()2380 TreeMapEntry<K,V> subHighest() { return absLowest(); } subCeiling(K key)2381 TreeMapEntry<K,V> subCeiling(K key) { return absFloor(key); } subHigher(K key)2382 TreeMapEntry<K,V> subHigher(K key) { return absLower(key); } subFloor(K key)2383 TreeMapEntry<K,V> subFloor(K key) { return absCeiling(key); } subLower(K key)2384 TreeMapEntry<K,V> subLower(K key) { return absHigher(key); } 2385 } 2386 2387 /** 2388 * This class exists solely for the sake of serialization 2389 * compatibility with previous releases of TreeMap that did not 2390 * support NavigableMap. It translates an old-version SubMap into 2391 * a new-version AscendingSubMap. This class is never otherwise 2392 * used. 2393 * 2394 * @serial include 2395 */ 2396 private class SubMap extends AbstractMap<K,V> 2397 implements SortedMap<K,V>, java.io.Serializable { 2398 @java.io.Serial 2399 private static final long serialVersionUID = -6520786458950516097L; 2400 private boolean fromStart = false, toEnd = false; 2401 @SuppressWarnings("serial") // Conditionally serializable 2402 private K fromKey; 2403 @SuppressWarnings("serial") // Conditionally serializable 2404 private K toKey; 2405 @java.io.Serial readResolve()2406 private Object readResolve() { 2407 return new AscendingSubMap<>(TreeMap.this, 2408 fromStart, fromKey, true, 2409 toEnd, toKey, false); 2410 } entrySet()2411 public Set<Map.Entry<K,V>> entrySet() { throw new InternalError(); } lastKey()2412 public K lastKey() { throw new InternalError(); } firstKey()2413 public K firstKey() { throw new InternalError(); } subMap(K fromKey, K toKey)2414 public SortedMap<K,V> subMap(K fromKey, K toKey) { throw new InternalError(); } headMap(K toKey)2415 public SortedMap<K,V> headMap(K toKey) { throw new InternalError(); } tailMap(K fromKey)2416 public SortedMap<K,V> tailMap(K fromKey) { throw new InternalError(); } comparator()2417 public Comparator<? super K> comparator() { throw new InternalError(); } 2418 } 2419 2420 2421 // Red-black mechanics 2422 2423 private static final boolean RED = false; 2424 private static final boolean BLACK = true; 2425 2426 /** 2427 * Node in the Tree. Doubles as a means to pass key-value pairs back to 2428 * user (see Map.Entry). 2429 */ 2430 // BEGIN Android-changed: Renamed Entry -> TreeMapEntry. 2431 // Code references to "TreeMap.Entry" must mean Map.Entry 2432 // 2433 // This mirrors the corresponding rename of LinkedHashMap's 2434 // Entry->LinkedHashMapEntry. 2435 // 2436 // This is for source compatibility with earlier versions of Android. 2437 // Otherwise, it would hide Map.Entry. 2438 // END Android-changed: Renamed Entry -> TreeMapEntry. 2439 static final class TreeMapEntry<K,V> implements Map.Entry<K,V> { 2440 K key; 2441 V value; 2442 TreeMapEntry<K,V> left; 2443 TreeMapEntry<K,V> right; 2444 TreeMapEntry<K,V> parent; 2445 boolean color = BLACK; 2446 2447 /** 2448 * Make a new cell with given key, value, and parent, and with 2449 * {@code null} child links, and BLACK color. 2450 */ TreeMapEntry(K key, V value, TreeMapEntry<K,V> parent)2451 TreeMapEntry(K key, V value, TreeMapEntry<K,V> parent) { 2452 this.key = key; 2453 this.value = value; 2454 this.parent = parent; 2455 } 2456 2457 /** 2458 * Returns the key. 2459 * 2460 * @return the key 2461 */ getKey()2462 public K getKey() { 2463 return key; 2464 } 2465 2466 /** 2467 * Returns the value associated with the key. 2468 * 2469 * @return the value associated with the key 2470 */ getValue()2471 public V getValue() { 2472 return value; 2473 } 2474 2475 /** 2476 * Replaces the value currently associated with the key with the given 2477 * value. 2478 * 2479 * @return the value associated with the key before this method was 2480 * called 2481 */ setValue(V value)2482 public V setValue(V value) { 2483 V oldValue = this.value; 2484 this.value = value; 2485 return oldValue; 2486 } 2487 equals(Object o)2488 public boolean equals(Object o) { 2489 return o instanceof Map.Entry<?, ?> e 2490 && valEquals(key,e.getKey()) 2491 && valEquals(value,e.getValue()); 2492 } 2493 hashCode()2494 public int hashCode() { 2495 int keyHash = (key==null ? 0 : key.hashCode()); 2496 int valueHash = (value==null ? 0 : value.hashCode()); 2497 return keyHash ^ valueHash; 2498 } 2499 toString()2500 public String toString() { 2501 return key + "=" + value; 2502 } 2503 } 2504 2505 /** 2506 * Returns the first Entry in the TreeMap (according to the TreeMap's 2507 * key-sort function). Returns null if the TreeMap is empty. 2508 */ getFirstEntry()2509 final TreeMapEntry<K,V> getFirstEntry() { 2510 TreeMapEntry<K,V> p = root; 2511 if (p != null) 2512 while (p.left != null) 2513 p = p.left; 2514 return p; 2515 } 2516 2517 /** 2518 * Returns the last Entry in the TreeMap (according to the TreeMap's 2519 * key-sort function). Returns null if the TreeMap is empty. 2520 */ getLastEntry()2521 final TreeMapEntry<K,V> getLastEntry() { 2522 TreeMapEntry<K,V> p = root; 2523 if (p != null) 2524 while (p.right != null) 2525 p = p.right; 2526 return p; 2527 } 2528 2529 /** 2530 * Returns the successor of the specified Entry, or null if no such. 2531 */ successor(TreeMapEntry<K,V> t)2532 static <K,V> TreeMapEntry<K,V> successor(TreeMapEntry<K,V> t) { 2533 if (t == null) 2534 return null; 2535 else if (t.right != null) { 2536 TreeMapEntry<K,V> p = t.right; 2537 while (p.left != null) 2538 p = p.left; 2539 return p; 2540 } else { 2541 TreeMapEntry<K,V> p = t.parent; 2542 TreeMapEntry<K,V> ch = t; 2543 while (p != null && ch == p.right) { 2544 ch = p; 2545 p = p.parent; 2546 } 2547 return p; 2548 } 2549 } 2550 2551 /** 2552 * Returns the predecessor of the specified Entry, or null if no such. 2553 */ predecessor(TreeMapEntry<K,V> t)2554 static <K,V> TreeMapEntry<K,V> predecessor(TreeMapEntry<K,V> t) { 2555 if (t == null) 2556 return null; 2557 else if (t.left != null) { 2558 TreeMapEntry<K,V> p = t.left; 2559 while (p.right != null) 2560 p = p.right; 2561 return p; 2562 } else { 2563 TreeMapEntry<K,V> p = t.parent; 2564 TreeMapEntry<K,V> ch = t; 2565 while (p != null && ch == p.left) { 2566 ch = p; 2567 p = p.parent; 2568 } 2569 return p; 2570 } 2571 } 2572 2573 /** 2574 * Balancing operations. 2575 * 2576 * Implementations of rebalancings during insertion and deletion are 2577 * slightly different than the CLR version. Rather than using dummy 2578 * nilnodes, we use a set of accessors that deal properly with null. They 2579 * are used to avoid messiness surrounding nullness checks in the main 2580 * algorithms. 2581 */ 2582 colorOf(TreeMapEntry<K,V> p)2583 private static <K,V> boolean colorOf(TreeMapEntry<K,V> p) { 2584 return (p == null ? BLACK : p.color); 2585 } 2586 parentOf(TreeMapEntry<K,V> p)2587 private static <K,V> TreeMapEntry<K,V> parentOf(TreeMapEntry<K,V> p) { 2588 return (p == null ? null: p.parent); 2589 } 2590 setColor(TreeMapEntry<K,V> p, boolean c)2591 private static <K,V> void setColor(TreeMapEntry<K,V> p, boolean c) { 2592 if (p != null) 2593 p.color = c; 2594 } 2595 leftOf(TreeMapEntry<K,V> p)2596 private static <K,V> TreeMapEntry<K,V> leftOf(TreeMapEntry<K,V> p) { 2597 return (p == null) ? null: p.left; 2598 } 2599 rightOf(TreeMapEntry<K,V> p)2600 private static <K,V> TreeMapEntry<K,V> rightOf(TreeMapEntry<K,V> p) { 2601 return (p == null) ? null: p.right; 2602 } 2603 2604 /** From CLR */ rotateLeft(TreeMapEntry<K,V> p)2605 private void rotateLeft(TreeMapEntry<K,V> p) { 2606 if (p != null) { 2607 TreeMapEntry<K,V> r = p.right; 2608 p.right = r.left; 2609 if (r.left != null) 2610 r.left.parent = p; 2611 r.parent = p.parent; 2612 if (p.parent == null) 2613 root = r; 2614 else if (p.parent.left == p) 2615 p.parent.left = r; 2616 else 2617 p.parent.right = r; 2618 r.left = p; 2619 p.parent = r; 2620 } 2621 } 2622 2623 /** From CLR */ rotateRight(TreeMapEntry<K,V> p)2624 private void rotateRight(TreeMapEntry<K,V> p) { 2625 if (p != null) { 2626 TreeMapEntry<K,V> l = p.left; 2627 p.left = l.right; 2628 if (l.right != null) l.right.parent = p; 2629 l.parent = p.parent; 2630 if (p.parent == null) 2631 root = l; 2632 else if (p.parent.right == p) 2633 p.parent.right = l; 2634 else p.parent.left = l; 2635 l.right = p; 2636 p.parent = l; 2637 } 2638 } 2639 2640 /** From CLR */ fixAfterInsertion(TreeMapEntry<K,V> x)2641 private void fixAfterInsertion(TreeMapEntry<K,V> x) { 2642 x.color = RED; 2643 2644 while (x != null && x != root && x.parent.color == RED) { 2645 if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { 2646 TreeMapEntry<K,V> y = rightOf(parentOf(parentOf(x))); 2647 if (colorOf(y) == RED) { 2648 setColor(parentOf(x), BLACK); 2649 setColor(y, BLACK); 2650 setColor(parentOf(parentOf(x)), RED); 2651 x = parentOf(parentOf(x)); 2652 } else { 2653 if (x == rightOf(parentOf(x))) { 2654 x = parentOf(x); 2655 rotateLeft(x); 2656 } 2657 setColor(parentOf(x), BLACK); 2658 setColor(parentOf(parentOf(x)), RED); 2659 rotateRight(parentOf(parentOf(x))); 2660 } 2661 } else { 2662 TreeMapEntry<K,V> y = leftOf(parentOf(parentOf(x))); 2663 if (colorOf(y) == RED) { 2664 setColor(parentOf(x), BLACK); 2665 setColor(y, BLACK); 2666 setColor(parentOf(parentOf(x)), RED); 2667 x = parentOf(parentOf(x)); 2668 } else { 2669 if (x == leftOf(parentOf(x))) { 2670 x = parentOf(x); 2671 rotateRight(x); 2672 } 2673 setColor(parentOf(x), BLACK); 2674 setColor(parentOf(parentOf(x)), RED); 2675 rotateLeft(parentOf(parentOf(x))); 2676 } 2677 } 2678 } 2679 root.color = BLACK; 2680 } 2681 2682 /** 2683 * Delete node p, and then rebalance the tree. 2684 */ deleteEntry(TreeMapEntry<K,V> p)2685 private void deleteEntry(TreeMapEntry<K,V> p) { 2686 modCount++; 2687 size--; 2688 2689 // If strictly internal, copy successor's element to p and then make p 2690 // point to successor. 2691 if (p.left != null && p.right != null) { 2692 TreeMapEntry<K,V> s = successor(p); 2693 p.key = s.key; 2694 p.value = s.value; 2695 p = s; 2696 } // p has 2 children 2697 2698 // Start fixup at replacement node, if it exists. 2699 TreeMapEntry<K,V> replacement = (p.left != null ? p.left : p.right); 2700 2701 if (replacement != null) { 2702 // Link replacement to parent 2703 replacement.parent = p.parent; 2704 if (p.parent == null) 2705 root = replacement; 2706 else if (p == p.parent.left) 2707 p.parent.left = replacement; 2708 else 2709 p.parent.right = replacement; 2710 2711 // Null out links so they are OK to use by fixAfterDeletion. 2712 p.left = p.right = p.parent = null; 2713 2714 // Fix replacement 2715 if (p.color == BLACK) 2716 fixAfterDeletion(replacement); 2717 } else if (p.parent == null) { // return if we are the only node. 2718 root = null; 2719 } else { // No children. Use self as phantom replacement and unlink. 2720 if (p.color == BLACK) 2721 fixAfterDeletion(p); 2722 2723 if (p.parent != null) { 2724 if (p == p.parent.left) 2725 p.parent.left = null; 2726 else if (p == p.parent.right) 2727 p.parent.right = null; 2728 p.parent = null; 2729 } 2730 } 2731 } 2732 2733 /** From CLR */ fixAfterDeletion(TreeMapEntry<K,V> x)2734 private void fixAfterDeletion(TreeMapEntry<K,V> x) { 2735 while (x != root && colorOf(x) == BLACK) { 2736 if (x == leftOf(parentOf(x))) { 2737 TreeMapEntry<K,V> sib = rightOf(parentOf(x)); 2738 2739 if (colorOf(sib) == RED) { 2740 setColor(sib, BLACK); 2741 setColor(parentOf(x), RED); 2742 rotateLeft(parentOf(x)); 2743 sib = rightOf(parentOf(x)); 2744 } 2745 2746 if (colorOf(leftOf(sib)) == BLACK && 2747 colorOf(rightOf(sib)) == BLACK) { 2748 setColor(sib, RED); 2749 x = parentOf(x); 2750 } else { 2751 if (colorOf(rightOf(sib)) == BLACK) { 2752 setColor(leftOf(sib), BLACK); 2753 setColor(sib, RED); 2754 rotateRight(sib); 2755 sib = rightOf(parentOf(x)); 2756 } 2757 setColor(sib, colorOf(parentOf(x))); 2758 setColor(parentOf(x), BLACK); 2759 setColor(rightOf(sib), BLACK); 2760 rotateLeft(parentOf(x)); 2761 x = root; 2762 } 2763 } else { // symmetric 2764 TreeMapEntry<K,V> sib = leftOf(parentOf(x)); 2765 2766 if (colorOf(sib) == RED) { 2767 setColor(sib, BLACK); 2768 setColor(parentOf(x), RED); 2769 rotateRight(parentOf(x)); 2770 sib = leftOf(parentOf(x)); 2771 } 2772 2773 if (colorOf(rightOf(sib)) == BLACK && 2774 colorOf(leftOf(sib)) == BLACK) { 2775 setColor(sib, RED); 2776 x = parentOf(x); 2777 } else { 2778 if (colorOf(leftOf(sib)) == BLACK) { 2779 setColor(rightOf(sib), BLACK); 2780 setColor(sib, RED); 2781 rotateLeft(sib); 2782 sib = leftOf(parentOf(x)); 2783 } 2784 setColor(sib, colorOf(parentOf(x))); 2785 setColor(parentOf(x), BLACK); 2786 setColor(leftOf(sib), BLACK); 2787 rotateRight(parentOf(x)); 2788 x = root; 2789 } 2790 } 2791 } 2792 2793 setColor(x, BLACK); 2794 } 2795 2796 @java.io.Serial 2797 private static final long serialVersionUID = 919286545866124006L; 2798 2799 /** 2800 * Save the state of the {@code TreeMap} instance to a stream (i.e., 2801 * serialize it). 2802 * 2803 * @serialData The <em>size</em> of the TreeMap (the number of key-value 2804 * mappings) is emitted (int), followed by the key (Object) 2805 * and value (Object) for each key-value mapping represented 2806 * by the TreeMap. The key-value mappings are emitted in 2807 * key-order (as determined by the TreeMap's Comparator, 2808 * or by the keys' natural ordering if the TreeMap has no 2809 * Comparator). 2810 */ 2811 @java.io.Serial writeObject(java.io.ObjectOutputStream s)2812 private void writeObject(java.io.ObjectOutputStream s) 2813 throws java.io.IOException { 2814 // Write out the Comparator and any hidden stuff 2815 s.defaultWriteObject(); 2816 2817 // Write out size (number of Mappings) 2818 s.writeInt(size); 2819 2820 // Write out keys and values (alternating) 2821 for (Map.Entry<K, V> e : entrySet()) { 2822 s.writeObject(e.getKey()); 2823 s.writeObject(e.getValue()); 2824 } 2825 } 2826 2827 /** 2828 * Reconstitute the {@code TreeMap} instance from a stream (i.e., 2829 * deserialize it). 2830 */ 2831 @java.io.Serial readObject(final java.io.ObjectInputStream s)2832 private void readObject(final java.io.ObjectInputStream s) 2833 throws java.io.IOException, ClassNotFoundException { 2834 // Read in the Comparator and any hidden stuff 2835 s.defaultReadObject(); 2836 2837 // Read in size 2838 int size = s.readInt(); 2839 2840 buildFromSorted(size, null, s, null); 2841 } 2842 2843 /** Intended to be called only from TreeSet.readObject */ readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal)2844 void readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal) 2845 throws java.io.IOException, ClassNotFoundException { 2846 buildFromSorted(size, null, s, defaultVal); 2847 } 2848 2849 /** Intended to be called only from TreeSet.addAll */ addAllForTreeSet(SortedSet<? extends K> set, V defaultVal)2850 void addAllForTreeSet(SortedSet<? extends K> set, V defaultVal) { 2851 try { 2852 buildFromSorted(set.size(), set.iterator(), null, defaultVal); 2853 } catch (java.io.IOException | ClassNotFoundException cannotHappen) { 2854 } 2855 } 2856 2857 2858 /** 2859 * Linear time tree building algorithm from sorted data. Can accept keys 2860 * and/or values from iterator or stream. This leads to too many 2861 * parameters, but seems better than alternatives. The four formats 2862 * that this method accepts are: 2863 * 2864 * 1) An iterator of Map.Entries. (it != null, defaultVal == null). 2865 * 2) An iterator of keys. (it != null, defaultVal != null). 2866 * 3) A stream of alternating serialized keys and values. 2867 * (it == null, defaultVal == null). 2868 * 4) A stream of serialized keys. (it == null, defaultVal != null). 2869 * 2870 * It is assumed that the comparator of the TreeMap is already set prior 2871 * to calling this method. 2872 * 2873 * @param size the number of keys (or key-value pairs) to be read from 2874 * the iterator or stream 2875 * @param it If non-null, new entries are created from entries 2876 * or keys read from this iterator. 2877 * @param str If non-null, new entries are created from keys and 2878 * possibly values read from this stream in serialized form. 2879 * Exactly one of it and str should be non-null. 2880 * @param defaultVal if non-null, this default value is used for 2881 * each value in the map. If null, each value is read from 2882 * iterator or stream, as described above. 2883 * @throws java.io.IOException propagated from stream reads. This cannot 2884 * occur if str is null. 2885 * @throws ClassNotFoundException propagated from readObject. 2886 * This cannot occur if str is null. 2887 */ buildFromSorted(int size, Iterator<?> it, java.io.ObjectInputStream str, V defaultVal)2888 private void buildFromSorted(int size, Iterator<?> it, 2889 java.io.ObjectInputStream str, 2890 V defaultVal) 2891 throws java.io.IOException, ClassNotFoundException { 2892 this.size = size; 2893 root = buildFromSorted(0, 0, size-1, computeRedLevel(size), 2894 it, str, defaultVal); 2895 } 2896 2897 /** 2898 * Recursive "helper method" that does the real work of the 2899 * previous method. Identically named parameters have 2900 * identical definitions. Additional parameters are documented below. 2901 * It is assumed that the comparator and size fields of the TreeMap are 2902 * already set prior to calling this method. (It ignores both fields.) 2903 * 2904 * @param level the current level of tree. Initial call should be 0. 2905 * @param lo the first element index of this subtree. Initial should be 0. 2906 * @param hi the last element index of this subtree. Initial should be 2907 * size-1. 2908 * @param redLevel the level at which nodes should be red. 2909 * Must be equal to computeRedLevel for tree of this size. 2910 */ 2911 @SuppressWarnings("unchecked") buildFromSorted(int level, int lo, int hi, int redLevel, Iterator<?> it, java.io.ObjectInputStream str, V defaultVal)2912 private final TreeMapEntry<K,V> buildFromSorted(int level, int lo, int hi, 2913 int redLevel, 2914 Iterator<?> it, 2915 java.io.ObjectInputStream str, 2916 V defaultVal) 2917 throws java.io.IOException, ClassNotFoundException { 2918 /* 2919 * Strategy: The root is the middlemost element. To get to it, we 2920 * have to first recursively construct the entire left subtree, 2921 * so as to grab all of its elements. We can then proceed with right 2922 * subtree. 2923 * 2924 * The lo and hi arguments are the minimum and maximum 2925 * indices to pull out of the iterator or stream for current subtree. 2926 * They are not actually indexed, we just proceed sequentially, 2927 * ensuring that items are extracted in corresponding order. 2928 */ 2929 2930 if (hi < lo) return null; 2931 2932 int mid = (lo + hi) >>> 1; 2933 2934 TreeMapEntry<K,V> left = null; 2935 if (lo < mid) 2936 left = buildFromSorted(level+1, lo, mid - 1, redLevel, 2937 it, str, defaultVal); 2938 2939 // extract key and/or value from iterator or stream 2940 K key; 2941 V value; 2942 if (it != null) { 2943 if (defaultVal==null) { 2944 Map.Entry<?,?> entry = (Map.Entry<?,?>)it.next(); 2945 key = (K)entry.getKey(); 2946 value = (V)entry.getValue(); 2947 } else { 2948 key = (K)it.next(); 2949 value = defaultVal; 2950 } 2951 } else { // use stream 2952 key = (K) str.readObject(); 2953 value = (defaultVal != null ? defaultVal : (V) str.readObject()); 2954 } 2955 2956 TreeMapEntry<K,V> middle = new TreeMapEntry<>(key, value, null); 2957 2958 // color nodes in non-full bottommost level red 2959 if (level == redLevel) 2960 middle.color = RED; 2961 2962 if (left != null) { 2963 middle.left = left; 2964 left.parent = middle; 2965 } 2966 2967 if (mid < hi) { 2968 TreeMapEntry<K,V> right = buildFromSorted(level+1, mid+1, hi, redLevel, 2969 it, str, defaultVal); 2970 middle.right = right; 2971 right.parent = middle; 2972 } 2973 2974 return middle; 2975 } 2976 2977 /** 2978 * Finds the level down to which to assign all nodes BLACK. This is the 2979 * last `full' level of the complete binary tree produced by buildTree. 2980 * The remaining nodes are colored RED. (This makes a `nice' set of 2981 * color assignments wrt future insertions.) This level number is 2982 * computed by finding the number of splits needed to reach the zeroeth 2983 * node. 2984 * 2985 * @param size the (non-negative) number of keys in the tree to be built 2986 */ computeRedLevel(int size)2987 private static int computeRedLevel(int size) { 2988 return 31 - Integer.numberOfLeadingZeros(size + 1); 2989 } 2990 2991 /** 2992 * Currently, we support Spliterator-based versions only for the 2993 * full map, in either plain of descending form, otherwise relying 2994 * on defaults because size estimation for submaps would dominate 2995 * costs. The type tests needed to check these for key views are 2996 * not very nice but avoid disrupting existing class 2997 * structures. Callers must use plain default spliterators if this 2998 * returns null. 2999 */ keySpliteratorFor(NavigableMap<K,?> m)3000 static <K> Spliterator<K> keySpliteratorFor(NavigableMap<K,?> m) { 3001 if (m instanceof TreeMap) { 3002 @SuppressWarnings("unchecked") TreeMap<K,Object> t = 3003 (TreeMap<K,Object>) m; 3004 return t.keySpliterator(); 3005 } 3006 if (m instanceof DescendingSubMap) { 3007 @SuppressWarnings("unchecked") DescendingSubMap<K,?> dm = 3008 (DescendingSubMap<K,?>) m; 3009 TreeMap<K,?> tm = dm.m; 3010 if (dm == tm.descendingMap) { 3011 @SuppressWarnings("unchecked") TreeMap<K,Object> t = 3012 (TreeMap<K,Object>) tm; 3013 return t.descendingKeySpliterator(); 3014 } 3015 } 3016 @SuppressWarnings("unchecked") NavigableSubMap<K,?> sm = 3017 (NavigableSubMap<K,?>) m; 3018 return sm.keySpliterator(); 3019 } 3020 keySpliterator()3021 final Spliterator<K> keySpliterator() { 3022 return new KeySpliterator<>(this, null, null, 0, -1, 0); 3023 } 3024 descendingKeySpliterator()3025 final Spliterator<K> descendingKeySpliterator() { 3026 return new DescendingKeySpliterator<>(this, null, null, 0, -2, 0); 3027 } 3028 3029 /** 3030 * Base class for spliterators. Iteration starts at a given 3031 * origin and continues up to but not including a given fence (or 3032 * null for end). At top-level, for ascending cases, the first 3033 * split uses the root as left-fence/right-origin. From there, 3034 * right-hand splits replace the current fence with its left 3035 * child, also serving as origin for the split-off spliterator. 3036 * Left-hands are symmetric. Descending versions place the origin 3037 * at the end and invert ascending split rules. This base class 3038 * is non-committal about directionality, or whether the top-level 3039 * spliterator covers the whole tree. This means that the actual 3040 * split mechanics are located in subclasses. Some of the subclass 3041 * trySplit methods are identical (except for return types), but 3042 * not nicely factorable. 3043 * 3044 * Currently, subclass versions exist only for the full map 3045 * (including descending keys via its descendingMap). Others are 3046 * possible but currently not worthwhile because submaps require 3047 * O(n) computations to determine size, which substantially limits 3048 * potential speed-ups of using custom Spliterators versus default 3049 * mechanics. 3050 * 3051 * To bootstrap initialization, external constructors use 3052 * negative size estimates: -1 for ascend, -2 for descend. 3053 */ 3054 static class TreeMapSpliterator<K,V> { 3055 final TreeMap<K,V> tree; 3056 TreeMapEntry<K,V> current; // traverser; initially first node in range 3057 TreeMapEntry<K,V> fence; // one past last, or null 3058 int side; // 0: top, -1: is a left split, +1: right 3059 int est; // size estimate (exact only for top-level) 3060 int expectedModCount; // for CME checks 3061 TreeMapSpliterator(TreeMap<K,V> tree, TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, int side, int est, int expectedModCount)3062 TreeMapSpliterator(TreeMap<K,V> tree, 3063 TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, 3064 int side, int est, int expectedModCount) { 3065 this.tree = tree; 3066 this.current = origin; 3067 this.fence = fence; 3068 this.side = side; 3069 this.est = est; 3070 this.expectedModCount = expectedModCount; 3071 } 3072 getEstimate()3073 final int getEstimate() { // force initialization 3074 int s; TreeMap<K,V> t; 3075 if ((s = est) < 0) { 3076 if ((t = tree) != null) { 3077 current = (s == -1) ? t.getFirstEntry() : t.getLastEntry(); 3078 s = est = t.size; 3079 expectedModCount = t.modCount; 3080 } 3081 else 3082 s = est = 0; 3083 } 3084 return s; 3085 } 3086 estimateSize()3087 public final long estimateSize() { 3088 return (long)getEstimate(); 3089 } 3090 } 3091 3092 static final class KeySpliterator<K,V> 3093 extends TreeMapSpliterator<K,V> 3094 implements Spliterator<K> { KeySpliterator(TreeMap<K,V> tree, TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, int side, int est, int expectedModCount)3095 KeySpliterator(TreeMap<K,V> tree, 3096 TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, 3097 int side, int est, int expectedModCount) { 3098 super(tree, origin, fence, side, est, expectedModCount); 3099 } 3100 trySplit()3101 public KeySpliterator<K,V> trySplit() { 3102 if (est < 0) 3103 getEstimate(); // force initialization 3104 int d = side; 3105 TreeMapEntry<K,V> e = current, f = fence, 3106 s = ((e == null || e == f) ? null : // empty 3107 (d == 0) ? tree.root : // was top 3108 (d > 0) ? e.right : // was right 3109 (d < 0 && f != null) ? f.left : // was left 3110 null); 3111 if (s != null && s != e && s != f && 3112 tree.compare(e.key, s.key) < 0) { // e not already past s 3113 side = 1; 3114 return new KeySpliterator<> 3115 (tree, e, current = s, -1, est >>>= 1, expectedModCount); 3116 } 3117 return null; 3118 } 3119 forEachRemaining(Consumer<? super K> action)3120 public void forEachRemaining(Consumer<? super K> action) { 3121 if (action == null) 3122 throw new NullPointerException(); 3123 if (est < 0) 3124 getEstimate(); // force initialization 3125 TreeMapEntry<K,V> f = fence, e, p, pl; 3126 if ((e = current) != null && e != f) { 3127 current = f; // exhaust 3128 do { 3129 action.accept(e.key); 3130 if ((p = e.right) != null) { 3131 while ((pl = p.left) != null) 3132 p = pl; 3133 } 3134 else { 3135 while ((p = e.parent) != null && e == p.right) 3136 e = p; 3137 } 3138 } while ((e = p) != null && e != f); 3139 if (tree.modCount != expectedModCount) 3140 throw new ConcurrentModificationException(); 3141 } 3142 } 3143 tryAdvance(Consumer<? super K> action)3144 public boolean tryAdvance(Consumer<? super K> action) { 3145 TreeMapEntry<K,V> e; 3146 if (action == null) 3147 throw new NullPointerException(); 3148 if (est < 0) 3149 getEstimate(); // force initialization 3150 if ((e = current) == null || e == fence) 3151 return false; 3152 current = successor(e); 3153 action.accept(e.key); 3154 if (tree.modCount != expectedModCount) 3155 throw new ConcurrentModificationException(); 3156 return true; 3157 } 3158 characteristics()3159 public int characteristics() { 3160 return (side == 0 ? Spliterator.SIZED : 0) | 3161 Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED; 3162 } 3163 getComparator()3164 public final Comparator<? super K> getComparator() { 3165 return tree.comparator; 3166 } 3167 3168 } 3169 3170 static final class DescendingKeySpliterator<K,V> 3171 extends TreeMapSpliterator<K,V> 3172 implements Spliterator<K> { DescendingKeySpliterator(TreeMap<K,V> tree, TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, int side, int est, int expectedModCount)3173 DescendingKeySpliterator(TreeMap<K,V> tree, 3174 TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, 3175 int side, int est, int expectedModCount) { 3176 super(tree, origin, fence, side, est, expectedModCount); 3177 } 3178 trySplit()3179 public DescendingKeySpliterator<K,V> trySplit() { 3180 if (est < 0) 3181 getEstimate(); // force initialization 3182 int d = side; 3183 TreeMapEntry<K,V> e = current, f = fence, 3184 s = ((e == null || e == f) ? null : // empty 3185 (d == 0) ? tree.root : // was top 3186 (d < 0) ? e.left : // was left 3187 (d > 0 && f != null) ? f.right : // was right 3188 null); 3189 if (s != null && s != e && s != f && 3190 tree.compare(e.key, s.key) > 0) { // e not already past s 3191 side = 1; 3192 return new DescendingKeySpliterator<> 3193 (tree, e, current = s, -1, est >>>= 1, expectedModCount); 3194 } 3195 return null; 3196 } 3197 forEachRemaining(Consumer<? super K> action)3198 public void forEachRemaining(Consumer<? super K> action) { 3199 if (action == null) 3200 throw new NullPointerException(); 3201 if (est < 0) 3202 getEstimate(); // force initialization 3203 TreeMapEntry<K,V> f = fence, e, p, pr; 3204 if ((e = current) != null && e != f) { 3205 current = f; // exhaust 3206 do { 3207 action.accept(e.key); 3208 if ((p = e.left) != null) { 3209 while ((pr = p.right) != null) 3210 p = pr; 3211 } 3212 else { 3213 while ((p = e.parent) != null && e == p.left) 3214 e = p; 3215 } 3216 } while ((e = p) != null && e != f); 3217 if (tree.modCount != expectedModCount) 3218 throw new ConcurrentModificationException(); 3219 } 3220 } 3221 tryAdvance(Consumer<? super K> action)3222 public boolean tryAdvance(Consumer<? super K> action) { 3223 TreeMapEntry<K,V> e; 3224 if (action == null) 3225 throw new NullPointerException(); 3226 if (est < 0) 3227 getEstimate(); // force initialization 3228 if ((e = current) == null || e == fence) 3229 return false; 3230 current = predecessor(e); 3231 action.accept(e.key); 3232 if (tree.modCount != expectedModCount) 3233 throw new ConcurrentModificationException(); 3234 return true; 3235 } 3236 characteristics()3237 public int characteristics() { 3238 return (side == 0 ? Spliterator.SIZED : 0) | 3239 Spliterator.DISTINCT | Spliterator.ORDERED; 3240 } 3241 } 3242 3243 static final class ValueSpliterator<K,V> 3244 extends TreeMapSpliterator<K,V> 3245 implements Spliterator<V> { ValueSpliterator(TreeMap<K,V> tree, TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, int side, int est, int expectedModCount)3246 ValueSpliterator(TreeMap<K,V> tree, 3247 TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, 3248 int side, int est, int expectedModCount) { 3249 super(tree, origin, fence, side, est, expectedModCount); 3250 } 3251 trySplit()3252 public ValueSpliterator<K,V> trySplit() { 3253 if (est < 0) 3254 getEstimate(); // force initialization 3255 int d = side; 3256 TreeMapEntry<K,V> e = current, f = fence, 3257 s = ((e == null || e == f) ? null : // empty 3258 (d == 0) ? tree.root : // was top 3259 (d > 0) ? e.right : // was right 3260 (d < 0 && f != null) ? f.left : // was left 3261 null); 3262 if (s != null && s != e && s != f && 3263 tree.compare(e.key, s.key) < 0) { // e not already past s 3264 side = 1; 3265 return new ValueSpliterator<> 3266 (tree, e, current = s, -1, est >>>= 1, expectedModCount); 3267 } 3268 return null; 3269 } 3270 forEachRemaining(Consumer<? super V> action)3271 public void forEachRemaining(Consumer<? super V> action) { 3272 if (action == null) 3273 throw new NullPointerException(); 3274 if (est < 0) 3275 getEstimate(); // force initialization 3276 TreeMapEntry<K,V> f = fence, e, p, pl; 3277 if ((e = current) != null && e != f) { 3278 current = f; // exhaust 3279 do { 3280 action.accept(e.value); 3281 if ((p = e.right) != null) { 3282 while ((pl = p.left) != null) 3283 p = pl; 3284 } 3285 else { 3286 while ((p = e.parent) != null && e == p.right) 3287 e = p; 3288 } 3289 } while ((e = p) != null && e != f); 3290 if (tree.modCount != expectedModCount) 3291 throw new ConcurrentModificationException(); 3292 } 3293 } 3294 tryAdvance(Consumer<? super V> action)3295 public boolean tryAdvance(Consumer<? super V> action) { 3296 TreeMapEntry<K,V> e; 3297 if (action == null) 3298 throw new NullPointerException(); 3299 if (est < 0) 3300 getEstimate(); // force initialization 3301 if ((e = current) == null || e == fence) 3302 return false; 3303 current = successor(e); 3304 action.accept(e.value); 3305 if (tree.modCount != expectedModCount) 3306 throw new ConcurrentModificationException(); 3307 return true; 3308 } 3309 characteristics()3310 public int characteristics() { 3311 return (side == 0 ? Spliterator.SIZED : 0) | Spliterator.ORDERED; 3312 } 3313 } 3314 3315 static final class EntrySpliterator<K,V> 3316 extends TreeMapSpliterator<K,V> 3317 implements Spliterator<Map.Entry<K,V>> { EntrySpliterator(TreeMap<K,V> tree, TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, int side, int est, int expectedModCount)3318 EntrySpliterator(TreeMap<K,V> tree, 3319 TreeMapEntry<K,V> origin, TreeMapEntry<K,V> fence, 3320 int side, int est, int expectedModCount) { 3321 super(tree, origin, fence, side, est, expectedModCount); 3322 } 3323 trySplit()3324 public EntrySpliterator<K,V> trySplit() { 3325 if (est < 0) 3326 getEstimate(); // force initialization 3327 int d = side; 3328 TreeMapEntry<K,V> e = current, f = fence, 3329 s = ((e == null || e == f) ? null : // empty 3330 (d == 0) ? tree.root : // was top 3331 (d > 0) ? e.right : // was right 3332 (d < 0 && f != null) ? f.left : // was left 3333 null); 3334 if (s != null && s != e && s != f && 3335 tree.compare(e.key, s.key) < 0) { // e not already past s 3336 side = 1; 3337 return new EntrySpliterator<> 3338 (tree, e, current = s, -1, est >>>= 1, expectedModCount); 3339 } 3340 return null; 3341 } 3342 forEachRemaining(Consumer<? super Map.Entry<K, V>> action)3343 public void forEachRemaining(Consumer<? super Map.Entry<K, V>> action) { 3344 if (action == null) 3345 throw new NullPointerException(); 3346 if (est < 0) 3347 getEstimate(); // force initialization 3348 TreeMapEntry<K,V> f = fence, e, p, pl; 3349 if ((e = current) != null && e != f) { 3350 current = f; // exhaust 3351 do { 3352 action.accept(e); 3353 if ((p = e.right) != null) { 3354 while ((pl = p.left) != null) 3355 p = pl; 3356 } 3357 else { 3358 while ((p = e.parent) != null && e == p.right) 3359 e = p; 3360 } 3361 } while ((e = p) != null && e != f); 3362 if (tree.modCount != expectedModCount) 3363 throw new ConcurrentModificationException(); 3364 } 3365 } 3366 tryAdvance(Consumer<? super Map.Entry<K,V>> action)3367 public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) { 3368 TreeMapEntry<K,V> e; 3369 if (action == null) 3370 throw new NullPointerException(); 3371 if (est < 0) 3372 getEstimate(); // force initialization 3373 if ((e = current) == null || e == fence) 3374 return false; 3375 current = successor(e); 3376 action.accept(e); 3377 if (tree.modCount != expectedModCount) 3378 throw new ConcurrentModificationException(); 3379 return true; 3380 } 3381 characteristics()3382 public int characteristics() { 3383 return (side == 0 ? Spliterator.SIZED : 0) | 3384 Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED; 3385 } 3386 3387 @Override getComparator()3388 public Comparator<Map.Entry<K, V>> getComparator() { 3389 // Adapt or create a key-based comparator 3390 if (tree.comparator != null) { 3391 return Map.Entry.comparingByKey(tree.comparator); 3392 } 3393 else { 3394 return (Comparator<Map.Entry<K, V>> & Serializable) (e1, e2) -> { 3395 @SuppressWarnings("unchecked") 3396 Comparable<? super K> k1 = (Comparable<? super K>) e1.getKey(); 3397 return k1.compareTo(e2.getKey()); 3398 }; 3399 } 3400 } 3401 } 3402 } 3403