TreeMap.java revision 59cb78e2355929587089ee436a0172af652d2aa5
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Copyright (C) 2010 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * you may not use this file except in compliance with the License. 6984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 10984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Unless required by applicable law or agreed to in writing, software 11984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * See the License for the specific language governing permissions and 14984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.util; 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream; 21984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport java.io.ObjectInputStream.GetField; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream; 23984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport java.io.ObjectStreamException; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable; 25984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Bound.EXCLUSIVE; 26984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Bound.INCLUSIVE; 27984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Bound.NO_BOUND; 28984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Relation.CEILING; 29984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Relation.EQUAL; 30984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Relation.FLOOR; 31984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Relation.HIGHER; 32984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonimport static java.util.TreeMap.Relation.LOWER; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 35984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * A map whose entries are sorted by their keys. All optional operations such as 36984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * {@link #put} and {@link #remove} are supported. 37984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 38984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <p>This map sorts keys using either a user-supplied comparator or the key's 39984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * natural order: 40984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <ul> 41984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <li>User supplied comparators must be able to compare any pair of keys in 42984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * this map. If a user-supplied comparator is in use, it will be returned 43984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * by {@link #comparator}. 44984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <li>If no user-supplied comparator is supplied, keys will be sorted by 45984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * their natural order. Keys must be <i>mutually comparable</i>: they must 46984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * implement {@link Comparable} and {@link Comparable#compareTo 47984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * compareTo()} must be able to compare each key with any other key in 48984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * this map. In this case {@link #comparator} will return null. 49984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * </ul> 50984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * With either a comparator or a natural ordering, comparisons should be 51984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <i>consistent with equals</i>. An ordering is consistent with equals if for 52984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * every pair of keys {@code a} and {@code b}, {@code a.equals(b)} if and only 53984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * if {@code compare(a, b) == 0}. 54984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 55984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <p>When the ordering is not consistent with equals the behavior of this 56984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * class is well defined but does not honor the contract specified by {@link 57984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Map}. Consider a tree map of case-insensitive strings, an ordering that is 58984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * not consistent with equals: <pre> {@code 59984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * TreeMap<String, String> map = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); 60984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * map.put("a", "android"); 61984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 62984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * // The Map API specifies that the next line should print "null" because 63984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * // "a".equals("A") is false and there is no mapping for upper case "A". 64984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * // But the case insensitive ordering says compare("a", "A") == 0. TreeMap 65984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * // uses only comparators/comparable on keys and so this prints "android". 66984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * System.out.println(map.get("A")); 67984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * }</pre> 68f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 69f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @since 1.2 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 71984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilsonpublic class TreeMap<K, V> extends AbstractMap<K, V> 72984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson implements SortedMap<K, V>, NavigableMap<K, V>, Cloneable, Serializable { 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 74984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // to avoid Comparable<Comparable<Comparable<...>>> 75984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private static final Comparator<Comparable> NATURAL_ORDER = new Comparator<Comparable>() { 76984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public int compare(Comparable a, Comparable b) { 77984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return a.compareTo(b); 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 79984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson }; 80984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 81984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Comparator<? super K> comparator; 82984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> root; 83984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int size = 0; 84984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int modCount = 0; 85984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 86984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 87984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Create a natural order, empty tree map whose keys must be mutually 88984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * comparable and non-null. 89984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 90984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // unsafe! this assumes K is comparable 91984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public TreeMap() { 92984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.comparator = (Comparator<? super K>) NATURAL_ORDER; 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 94f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 95984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 96984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Create a natural order tree map populated with the key/value pairs of 97984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * {@code copyFrom}. This map's keys must be mutually comparable and 98984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * non-null. 99984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 100984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <p>Even if {@code copyFrom} is a {@code SortedMap}, the constructed map 101984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <strong>will not</strong> use {@code copyFrom}'s ordering. This 102984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * constructor always creates a naturally-ordered map. Because the {@code 103984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * TreeMap} constructor overloads are ambiguous, prefer to construct a map 104984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * and populate it in two steps: <pre> {@code 105984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * TreeMap<String, Integer> customOrderedMap 106984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * = new TreeMap<String, Integer>(copyFrom.comparator()); 107984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * customOrderedMap.putAll(copyFrom); 108984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * }</pre> 109984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 110984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public TreeMap(Map<? extends K, ? extends V> copyFrom) { 111984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this(); 112984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson for (Map.Entry<? extends K, ? extends V> entry : copyFrom.entrySet()) { 113984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson putInternal(entry.getKey(), entry.getValue()); 11455392539fea537abfb6581b474918f9d611fba27Jesse Wilson } 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 117984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 118984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Create a tree map ordered by {@code comparator}. This map's keys may only 119984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * be null if {@code comparator} permits. 120984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 121984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * @parameter comparator the comparator to order elements with, or {@code 122984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * null} to use the natural ordering. 123984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 124984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // unsafe! if comparator is null, this assumes K is comparable 125984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public TreeMap(Comparator<? super K> comparator) { 126984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparator != null) { 127984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.comparator = comparator; 128984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { 129984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.comparator = (Comparator<? super K>) NATURAL_ORDER; 130984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 131984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 134984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Create a tree map with the ordering and key/value pairs of {@code 135984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * copyFrom}. This map's keys may only be null if the {@code copyFrom}'s 136984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * ordering permits. 137984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 138984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <p>The constructed map <strong>will always use</strong> {@code 139984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * copyFrom}'s ordering. Because the {@code TreeMap} constructor overloads 140984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * are ambigous, prefer to construct a map and populate it in two steps: 141984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <pre> {@code 142984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * TreeMap<String, Integer> customOrderedMap 143984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * = new TreeMap<String, Integer>(copyFrom.comparator()); 144984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * customOrderedMap.putAll(copyFrom); 145984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * }</pre> 146984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 147984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // if copyFrom's keys are comparable this map's keys must be also 148984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public TreeMap(SortedMap<K, ? extends V> copyFrom) { 149984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Comparator<? super K> sourceComparator = copyFrom.comparator(); 150984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (sourceComparator != null) { 151984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.comparator = sourceComparator; 152984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { 153984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.comparator = (Comparator<? super K>) NATURAL_ORDER; 154f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 155984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson for (Map.Entry<K, ? extends V> entry : copyFrom.entrySet()) { 156984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson putInternal(entry.getKey(), entry.getValue()); 157984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 158984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 159f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 160984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Object clone() { 161984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson try { 162984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // super.clone() must return the same type 163984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson TreeMap<K, V> map = (TreeMap<K, V>) super.clone(); 164d44d87eac62e1710d2cd420b00c05c98aebc8c98Jesse Wilson map.root = root != null ? root.copy(null) : null; 165984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson map.entrySet = null; 166984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson map.keySet = null; 167984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return map; 168984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } catch (CloneNotSupportedException e) { 169984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new AssertionError(); 170f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 171984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 172984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 173984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public int size() { 174984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return size; 175984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 176984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 177984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean isEmpty() { 178984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return size == 0; 179984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 180984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 181984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public V get(Object key) { 182984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<K, V> entry = findByObject(key); 183984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getValue() : null; 184984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 185984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 186984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean containsKey(Object key) { 187984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return findByObject(key) != null; 188984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 189984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 190984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public V put(K key, V value) { 191984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return putInternal(key, value); 192984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 193984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 194984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public void clear() { 195984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root = null; 196984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson size = 0; 197984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson modCount++; 198984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 199984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 200984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public V remove(Object key) { 201984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> node = removeInternalByKey(key); 202984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return node != null ? node.value : null; 203984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 204984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 205984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 206984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * AVL methods 207984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 208f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 209984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson enum Relation { 210984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson LOWER, 211984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson FLOOR, 212984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson EQUAL, 213984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson CREATE, 214984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson CEILING, 215984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson HIGHER; 216984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 217984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 218984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns a possibly-flipped relation for use in descending views. 219984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 220984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * @param ascending false to flip; true to return this. 221984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 222984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Relation forOrder(boolean ascending) { 223984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (ascending) { 224984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return this; 225984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 226984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 227984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson switch (this) { 228984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case LOWER: 229984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return HIGHER; 230984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case FLOOR: 231984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return CEILING; 232984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case EQUAL: 233984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return EQUAL; 234984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case CEILING: 235984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return FLOOR; 236984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case HIGHER: 237984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return LOWER; 238984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson default: 239984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new IllegalStateException(); 240984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 242984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 244984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson V putInternal(K key, V value) { 245984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> created = find(key, Relation.CREATE); 246984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson V result = created.value; 247984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson created.value = value; 248984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 249984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 250984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 251984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 252984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns the node at or adjacent to the given key, creating it if requested. 253984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 254984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * @throws ClassCastException if {@code key} and the tree's keys aren't mutually comparable. 255984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 256984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> find(K key, Relation relation) { 257984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (root == null) { 2583642569f572913df26e48b04f32b719cb1c38261Jesse Wilson if (comparator == NATURAL_ORDER && !(key instanceof Comparable)) { 2593642569f572913df26e48b04f32b719cb1c38261Jesse Wilson throw new ClassCastException(key.getClass().getName()); // NullPointerException ok 2603642569f572913df26e48b04f32b719cb1c38261Jesse Wilson } 261984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (relation == Relation.CREATE) { 262984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root = new Node<K, V>(null, key); 263984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson size = 1; 264984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson modCount++; 265984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return root; 266984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { 267984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return null; 268984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 269984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 270984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 271984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 272984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Micro-optimization: avoid polymorphic calls to Comparator.compare(). 273984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * This is 10% faster for naturally ordered trees. 274984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 275984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // will throw a ClassCastException below if there's trouble 276984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Comparable<Object> comparableKey = (comparator == NATURAL_ORDER) 277984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson ? (Comparable<Object>) key 278984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson : null; 279984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 280984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> nearest = root; 281984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson while (true) { 282984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int comparison = (comparableKey != null) 283984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson ? comparableKey.compareTo(nearest.key) 284984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson : comparator.compare(key, nearest.key); 285984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 286984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 287984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * We found the requested key. 288984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 289984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparison == 0) { 290984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson switch (relation) { 291984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case LOWER: 292984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return nearest.prev(); 293984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case FLOOR: 294984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case EQUAL: 295984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case CREATE: 296984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case CEILING: 297984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return nearest; 298984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case HIGHER: 299984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return nearest.next(); 300984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 301984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 302984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 303984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> child = (comparison < 0) ? nearest.left : nearest.right; 304984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (child != null) { 305984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson nearest = child; 306984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson continue; 307984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 308984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 309984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 310984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * We found a nearest node. Every key not in the tree has up to two 311984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * nearest nodes, one lower and one higher. 312984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 313984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 314984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparison < 0) { // nearest.key is higher 315984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson switch (relation) { 316984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case LOWER: 317984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case FLOOR: 318984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return nearest.prev(); 319984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case CEILING: 320984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case HIGHER: 321984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return nearest; 322984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case EQUAL: 323984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return null; 324984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case CREATE: 325984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> created = new Node<K, V>(nearest, key); 326984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson nearest.left = created; 327984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson size++; 328984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson modCount++; 329984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rebalance(nearest, true); 330984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return created; 331984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 332984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { // comparison > 0, nearest.key is lower 333984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson switch (relation) { 334984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case LOWER: 335984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case FLOOR: 336984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return nearest; 337984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case CEILING: 338984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case HIGHER: 339984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return nearest.next(); 340984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case EQUAL: 341984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return null; 342984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case CREATE: 343984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> created = new Node<K, V>(nearest, key); 344984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson nearest.right = created; 345984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson size++; 346984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson modCount++; 347984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rebalance(nearest, true); 348984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return created; 349984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 350984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 352984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 354984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // this method throws ClassCastExceptions! 355984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> findByObject(Object key) { 356984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return find((K) key, EQUAL); 357984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 358984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 359984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 360984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns this map's entry that has the same key and value as {@code 361984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * entry}, or null if this map has no such entry. 362984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 363984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * <p>This method uses the comparator for key equality rather than {@code 364984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * equals}. If this map's comparator isn't consistent with equals (such as 365984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * {@code String.CASE_INSENSITIVE_ORDER}), then {@code remove()} and {@code 366984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * contains()} will violate the collections API. 367984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 368984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> findByEntry(Entry<?, ?> entry) { 369984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> mine = findByObject(entry.getKey()); 370984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean valuesEqual = mine != null && (mine.value != null 371984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson ? mine.value.equals(entry.getValue()) 372984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson : entry.getValue() == null); 373984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return valuesEqual ? mine : null; 374984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 375984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 376984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 377984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Removes {@code node} from this tree, rearranging the tree's structure as 378984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * necessary. 379984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 380984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson void removeInternal(Node<K, V> node) { 381984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> left = node.left; 382984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> right = node.right; 383984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> originalParent = node.parent; 384984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (left != null && right != null) { 385984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 386984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 387984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * To remove a node with both left and right subtrees, move an 388984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * adjacent node from one of those subtrees into this node's place. 389984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 390984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Removing the adjacent node may change this node's subtrees. This 391984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * node may no longer have two subtrees once the adjacent node is 392984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * gone! 393984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 394984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 395984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> adjacent = (left.height > right.height) ? left.last() : right.first(); 396984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(adjacent); // takes care of rebalance and size-- 397984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 398984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int leftHeight = 0; 399984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson left = node.left; 400984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (left != null) { 401984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson leftHeight = left.height; 402984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson adjacent.left = left; 403984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson left.parent = adjacent; 404984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node.left = null; 405f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 406984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int rightHeight = 0; 407984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson right = node.right; 408984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (right != null) { 409984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rightHeight = right.height; 410984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson adjacent.right = right; 411984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson right.parent = adjacent; 412984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node.right = null; 413984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 414984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson adjacent.height = Math.max(leftHeight, rightHeight) + 1; 415984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson replaceInParent(node, adjacent); 416984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return; 417984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (left != null) { 418984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson replaceInParent(node, left); 419984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node.left = null; 420984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (right != null) { 421984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson replaceInParent(node, right); 422984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node.right = null; 423984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { 424984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson replaceInParent(node, null); 425984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 426984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 427984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rebalance(originalParent, false); 428984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson size--; 429984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson modCount++; 430984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 431984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 432984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> removeInternalByKey(Object key) { 433984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> node = findByObject(key); 434984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (node != null) { 435984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(node); 436984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 437984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return node; 438984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 439984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 440984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private void replaceInParent(Node<K, V> node, Node<K, V> replacement) { 441984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> parent = node.parent; 442984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node.parent = null; 443984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (replacement != null) { 444984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson replacement.parent = parent; 445984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 446984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 447984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (parent != null) { 448984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (parent.left == node) { 449984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson parent.left = replacement; 450f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } else { 451984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson assert (parent.right == node); 452984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson parent.right = replacement; 453f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 454984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { 455984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root = replacement; 456f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 457984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 458f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 459984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 460984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Rebalances the tree by making any AVL rotations necessary between the 461984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * newly-unbalanced node and the tree's root. 462984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * 463984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * @param insert true if the node was unbalanced by an insert; false if it 464984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * was by a removal. 465984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 466984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private void rebalance(Node<K, V> unbalanced, boolean insert) { 467984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson for (Node<K, V> node = unbalanced; node != null; node = node.parent) { 468984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> left = node.left; 469984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> right = node.right; 470984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int leftHeight = left != null ? left.height : 0; 471984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int rightHeight = right != null ? right.height : 0; 472984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 473984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int delta = leftHeight - rightHeight; 474984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (delta == -2) { 475984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> rightLeft = right.left; 476984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> rightRight = right.right; 477984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int rightRightHeight = rightRight != null ? rightRight.height : 0; 478984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int rightLeftHeight = rightLeft != null ? rightLeft.height : 0; 479984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 480984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int rightDelta = rightLeftHeight - rightRightHeight; 481984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (rightDelta == -1 || (rightDelta == 0 && !insert)) { 482984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rotateLeft(node); // AVL right right 483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 484984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson assert (rightDelta == 1); 485984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rotateRight(right); // AVL right left 486984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rotateLeft(node); 487984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 488984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (insert) { 489984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; // no further rotations will be necessary 490984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 491984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 492984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (delta == 2) { 493984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> leftLeft = left.left; 494984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> leftRight = left.right; 495984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int leftRightHeight = leftRight != null ? leftRight.height : 0; 496984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int leftLeftHeight = leftLeft != null ? leftLeft.height : 0; 497984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 498984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int leftDelta = leftLeftHeight - leftRightHeight; 499984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (leftDelta == 1 || (leftDelta == 0 && !insert)) { 500984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rotateRight(node); // AVL left left 501984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { 502984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson assert (leftDelta == -1); 503984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rotateLeft(left); // AVL left right 504984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson rotateRight(node); 505984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 506984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (insert) { 507984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; // no further rotations will be necessary 508984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 509984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 510984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (delta == 0) { 511984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node.height = leftHeight + 1; // leftHeight == rightHeight 512984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (insert) { 513984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; // the insert caused balance, so rebalancing is done! 514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 515984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 517984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson assert (delta == -1 || delta == 1); 518984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node.height = Math.max(leftHeight, rightHeight) + 1; 519984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (!insert) { 520984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; // the height hasn't changed, so rebalancing is done! 521984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 524f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 526984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 527984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Rotates the subtree so that its root's right child is the new root. 528984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 529984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private void rotateLeft(Node<K, V> root) { 530984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> left = root.left; 531984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> pivot = root.right; 532984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> pivotLeft = pivot.left; 533984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> pivotRight = pivot.right; 534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 535984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson // move the pivot's left child to the root's right 536984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root.right = pivotLeft; 537984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (pivotLeft != null) { 538984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivotLeft.parent = root; 539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 541984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson replaceInParent(root, pivot); 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 543984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson // move the root to the pivot's left 544984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivot.left = root; 545984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root.parent = pivot; 546984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 547984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson // fix heights 548984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root.height = Math.max(left != null ? left.height : 0, 549984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivotLeft != null ? pivotLeft.height : 0) + 1; 550984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivot.height = Math.max(root.height, 551984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivotRight != null ? pivotRight.height : 0) + 1; 552f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 554984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 555984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Rotates the subtree so that its root's left child is the new root. 556984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 557984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private void rotateRight(Node<K, V> root) { 558984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> pivot = root.left; 559984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> right = root.right; 560984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> pivotLeft = pivot.left; 561984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> pivotRight = pivot.right; 562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 563984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson // move the pivot's right child to the root's left 564984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root.left = pivotRight; 565984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (pivotRight != null) { 566984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivotRight.parent = root; 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 569984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson replaceInParent(root, pivot); 570984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 571984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson // move the root to the pivot's right 572984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivot.right = root; 573984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root.parent = pivot; 574984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 575984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson // fixup heights 576984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson root.height = Math.max(right != null ? right.height : 0, 577984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivotRight != null ? pivotRight.height : 0) + 1; 578984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivot.height = Math.max(root.height, 579984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson pivotLeft != null ? pivotLeft.height : 0) + 1; 580984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 581984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 582984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 583984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Navigable methods. 584984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 585984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 58659cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe /** 58759cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe * Returns an immutable version of {@param entry}. Need this because we allow entry to be null, 58859cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe * in which case we return a null SimpleImmutableEntry. 58959cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe */ 59059cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe private SimpleImmutableEntry<K, V> immutableCopy(Entry<K, V> entry) { 59159cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return entry == null ? null : new SimpleImmutableEntry<K, V>(entry); 59259cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe } 59359cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe 594984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> firstEntry() { 59559cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(root == null ? null : root.first()); 596984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 597984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 5987cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe private Entry<K, V> internalPollFirstEntry() { 599984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (root == null) { 600984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return null; 601adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 602984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> result = root.first(); 603984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(result); 604984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 605984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6077cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe public Entry<K, V> pollFirstEntry() { 60859cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(internalPollFirstEntry()); 6097cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe } 6107cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe 611984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K firstKey() { 612984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (root == null) { 613984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new NoSuchElementException(); 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 615984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return root.first().getKey(); 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 618984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> lastEntry() { 61959cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(root == null ? null : root.last()); 620984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6227cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe private Entry<K, V> internalPollLastEntry() { 623984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (root == null) { 624984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return null; 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 626984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> result = root.last(); 627984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(result); 628984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 629984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6317cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe public Entry<K, V> pollLastEntry() { 63259cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(internalPollLastEntry()); 6337cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe } 6347cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe 635984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K lastKey() { 636984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (root == null) { 637984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new NoSuchElementException(); 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 639984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return root.last().getKey(); 640984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 642984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> lowerEntry(K key) { 64359cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(find(key, LOWER)); 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 646984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K lowerKey(K key) { 647984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<K, V> entry = find(key, LOWER); 648984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 649984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 651984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> floorEntry(K key) { 65259cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(find(key, FLOOR)); 653984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 655984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K floorKey(K key) { 656984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<K, V> entry = find(key, FLOOR); 657984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 658984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 660984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> ceilingEntry(K key) { 66159cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(find(key, CEILING)); 662984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 664984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K ceilingKey(K key) { 665984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<K, V> entry = find(key, CEILING); 666984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 667984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 669984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> higherEntry(K key) { 67059cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(find(key, HIGHER)); 671984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 672984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 673984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K higherKey(K key) { 674984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<K, V> entry = find(key, HIGHER); 675984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 678984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Comparator<? super K> comparator() { 679984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return comparator != NATURAL_ORDER ? comparator : null; 680984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 682984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 683984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * View factory methods. 684984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 686984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private EntrySet entrySet; 687984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private KeySet keySet; 688984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 689984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Set<Entry<K, V>> entrySet() { 690984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson EntrySet result = entrySet; 691984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result != null ? result : (entrySet = new EntrySet()); 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 694984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Set<K> keySet() { 695984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson KeySet result = keySet; 696984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result != null ? result : (keySet = new KeySet()); 697984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 699984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> navigableKeySet() { 700984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson KeySet result = keySet; 701984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result != null ? result : (keySet = new KeySet()); 702984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 704984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive) { 705984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound fromBound = fromInclusive ? INCLUSIVE : EXCLUSIVE; 706984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound toBound = toInclusive ? INCLUSIVE : EXCLUSIVE; 707984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(true, from, fromBound, to, toBound); 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 710984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedMap<K, V> subMap(K fromInclusive, K toExclusive) { 711984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(true, fromInclusive, INCLUSIVE, toExclusive, EXCLUSIVE); 712984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 714984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> headMap(K to, boolean inclusive) { 715984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound toBound = inclusive ? INCLUSIVE : EXCLUSIVE; 716984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(true, null, NO_BOUND, to, toBound); 717984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 719984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedMap<K, V> headMap(K toExclusive) { 720984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(true, null, NO_BOUND, toExclusive, EXCLUSIVE); 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 723984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> tailMap(K from, boolean inclusive) { 724984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound fromBound = inclusive ? INCLUSIVE : EXCLUSIVE; 725984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(true, from, fromBound, null, NO_BOUND); 726984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 728984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedMap<K, V> tailMap(K fromInclusive) { 729984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(true, fromInclusive, INCLUSIVE, null, NO_BOUND); 730984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 732984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> descendingMap() { 733984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(false, null, NO_BOUND, null, NO_BOUND); 734984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 736984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> descendingKeySet() { 737984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(false, null, NO_BOUND, null, NO_BOUND).navigableKeySet(); 738984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 740984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson static class Node<K, V> implements Map.Entry<K, V> { 741984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> parent; 742984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> left; 743984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> right; 744984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson final K key; 745984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson V value; 746984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int height; 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 748984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node(Node<K, V> parent, K key) { 749984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.parent = parent; 750984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.key = key; 751984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.height = 1; 752f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 754984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> copy(Node<K, V> parent) { 755984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> result = new Node<K, V>(parent, key); 756984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (left != null) { 757984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson result.left = left.copy(result); 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 759984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (right != null) { 760984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson result.right = right.copy(result); 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 762984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson result.value = value; 763984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson result.height = height; 764984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 765f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 767984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K getKey() { 768984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return key; 769f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 771984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public V getValue() { 772984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return value; 773f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 775984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public V setValue(V value) { 7767cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe V oldValue = this.value; 7777cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe this.value = value; 7787cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return oldValue; 779f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 780f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 781984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean equals(Object o) { 782984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (o instanceof Map.Entry) { 783984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Map.Entry other = (Map.Entry) o; 784984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return (key == null ? other.getKey() == null : key.equals(other.getKey())) 785984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson && (value == null ? other.getValue() == null : value.equals(other.getValue())); 786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 787f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return false; 788f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 789f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 790984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public int hashCode() { 791984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return (key == null ? 0 : key.hashCode()) 792984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson ^ (value == null ? 0 : value.hashCode()); 793f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 795984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public String toString() { 796984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return key + "=" + value; 797f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 799984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 800984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns the next node in an inorder traversal, or null if this is the 801984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * last node in the tree. 802984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 803984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> next() { 804984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (right != null) { 805984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return right.first(); 806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 808984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> node = this; 809984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> parent = node.parent; 810984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson while (parent != null) { 811984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (parent.left == node) { 812984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return parent; 813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 814984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node = parent; 815984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson parent = node.parent; 816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 817984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return null; 818f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 820984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 821984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns the previous node in an inorder traversal, or null if this is 822984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * the first node in the tree. 823984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 824984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Node<K, V> prev() { 825984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (left != null) { 826984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return left.last(); 827984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 829984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> node = this; 830984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> parent = node.parent; 831984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson while (parent != null) { 832984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (parent.right == node) { 833984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return parent; 834984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 835984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node = parent; 836984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson parent = node.parent; 837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 838f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson return null; 839f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 841984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 842984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns the first node in this subtree. 843984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 844984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Node<K, V> first() { 845984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> node = this; 846984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> child = node.left; 847984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson while (child != null) { 848984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node = child; 849984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson child = node.left; 850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 851984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return node; 852f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 854984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 855984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns the last node in this subtree. 856984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 857984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Node<K, V> last() { 858984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> node = this; 859984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> child = node.right; 860984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson while (child != null) { 861984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson node = child; 862984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson child = node.right; 863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 864984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return node; 865f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 866984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 868984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 869984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Walk the nodes of the tree left-to-right or right-to-left. Note that in 870984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * descending iterations, {@code next} will return the previous node. 871984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 872984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson abstract class MapIterator<T> implements Iterator<T> { 873984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson protected Node<K, V> next; 874984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson protected Node<K, V> last; 875984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson protected int expectedModCount = modCount; 876984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 877984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson MapIterator(Node<K, V> next) { 878984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.next = next; 879f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 881984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public boolean hasNext() { 882984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return next != null; 883984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 884984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 885984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson protected Node<K, V> stepForward() { 886984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (next == null) { 887984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new NoSuchElementException(); 888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 889984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (modCount != expectedModCount) { 890984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new ConcurrentModificationException(); 891f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 892984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson last = next; 893984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson next = next.next(); 894984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return last; 895f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 897984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson protected Node<K, V> stepBackward() { 898984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (next == null) { 899984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new NoSuchElementException(); 900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 901984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (modCount != expectedModCount) { 902984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new ConcurrentModificationException(); 903984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 904984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson last = next; 905984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson next = next.prev(); 906984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return last; 907f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 909984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public void remove() { 910984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (last == null) { 911984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new IllegalStateException(); 912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 913984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(last); 914984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson expectedModCount = modCount; 915984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson last = null; 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 917984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 919984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 920984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * View implementations. 921984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 922984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 923984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson class EntrySet extends AbstractSet<Map.Entry<K, V>> { 924984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public int size() { 925984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return size; 926f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 928984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Iterator<Entry<K, V>> iterator() { 9297cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return new MapIterator<Entry<K, V>>(root == null ? null : root.first()) { 930984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> next() { 931984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return stepForward(); 932f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 933984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson }; 934f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 936984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean contains(Object o) { 937984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return o instanceof Entry && findByEntry((Entry<?, ?>) o) != null; 938f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 940984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean remove(Object o) { 941984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (!(o instanceof Entry)) { 942984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; 943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 945984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> node = findByEntry((Entry<?, ?>) o); 946984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (node == null) { 947984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; 948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 949984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(node); 950984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return true; 951f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 953984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public void clear() { 954984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson TreeMap.this.clear(); 955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 956f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 958984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson class KeySet extends AbstractSet<K> implements NavigableSet<K> { 959984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public int size() { 960984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return size; 961984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 963984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Iterator<K> iterator() { 9647cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return new MapIterator<K>(root == null ? null : root.first()) { 965984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K next() { 966984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return stepForward().key; 967984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 968984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson }; 969f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 970adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 971984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Iterator<K> descendingIterator() { 9727cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return new MapIterator<K>(root == null ? null : root.last()) { 973984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K next() { 974984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return stepBackward().key; 975984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 976984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson }; 977f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 979984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean contains(Object o) { 980984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return containsKey(o); 981f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 983984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean remove(Object key) { 984984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return removeInternalByKey(key) != null; 985f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 986f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 987984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public void clear() { 988984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson TreeMap.this.clear(); 989f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 991984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Comparator<? super K> comparator() { 992984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.comparator(); 993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 995984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 996984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Navigable methods. 997984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 999984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K first() { 1000984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return firstKey(); 1001f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1002adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1003984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K last() { 1004984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return lastKey(); 1005f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1007984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K lower(K key) { 1008984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return lowerKey(key); 1009f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1010adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1011984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K floor(K key) { 1012984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return floorKey(key); 1013adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1015984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K ceiling(K key) { 1016984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return ceilingKey(key); 1017f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1018f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1019984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K higher(K key) { 1020984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return higherKey(key); 1021f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1022f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1023984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K pollFirst() { 10247cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe Entry<K, V> entry = internalPollFirstEntry(); 1025984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1026f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1027f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1028984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K pollLast() { 10297cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe Entry<K, V> entry = internalPollLastEntry(); 1030984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1031f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1032f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1033984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1034984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * View factory methods. 1035984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1036984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1037984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> subSet(K from, boolean fromInclusive, K to, boolean toInclusive) { 1038984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.subMap(from, fromInclusive, to, toInclusive).navigableKeySet(); 1039f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1040f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1041984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedSet<K> subSet(K fromInclusive, K toExclusive) { 1042984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.subMap(fromInclusive, true, toExclusive, false).navigableKeySet(); 1043f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1044f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1045984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> headSet(K to, boolean inclusive) { 1046984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.headMap(to, inclusive).navigableKeySet(); 1047984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1049984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedSet<K> headSet(K toExclusive) { 1050984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.headMap(toExclusive, false).navigableKeySet(); 1051984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1053984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> tailSet(K from, boolean inclusive) { 1054984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.tailMap(from, inclusive).navigableKeySet(); 1055984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1057984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedSet<K> tailSet(K fromInclusive) { 1058984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.tailMap(fromInclusive, true).navigableKeySet(); 1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1060adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1061984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> descendingSet() { 1062984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(false, null, NO_BOUND, null, NO_BOUND).navigableKeySet(); 1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1065adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1066984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1067984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Bounded views implementations. 1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1069984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1070984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson enum Bound { 10712f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson INCLUSIVE { 10722f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson @Override public String leftCap(Object from) { 10732f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return "[" + from; 10742f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 10752f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson @Override public String rightCap(Object to) { 10762f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return to + "]"; 10772f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 10782f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson }, 10792f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson EXCLUSIVE { 10802f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson @Override public String leftCap(Object from) { 10812f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return "(" + from; 10822f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 10832f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson @Override public String rightCap(Object to) { 10842f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return to + ")"; 10852f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 10862f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson }, 10872f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson NO_BOUND { 10882f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson @Override public String leftCap(Object from) { 10892f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return "."; 10902f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 10912f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson @Override public String rightCap(Object to) { 10922f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return "."; 10932f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 10942f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson }; 10952f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson 10962f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson public abstract String leftCap(Object from); 10972f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson public abstract String rightCap(Object to); 1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1101984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * A map with optional limits on its range. 1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1103984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson final class BoundedMap extends AbstractMap<K, V> implements NavigableMap<K, V>, Serializable { 1104984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private final boolean ascending; 1105984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private final K from; 1106984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private final Bound fromBound; 1107984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private final K to; 1108984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private final Bound toBound; 1109984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1110984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson BoundedMap(boolean ascending, K from, Bound fromBound, K to, Bound toBound) { 1111984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1112984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Validate the bounds. In addition to checking that from <= to, we 11132f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * verify that the comparator supports our bound objects. 1114984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1115984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (fromBound != NO_BOUND && toBound != NO_BOUND) { 1116984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparator.compare(from, to) > 0) { 1117984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new IllegalArgumentException(from + " > " + to); 1118f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1119984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (fromBound != NO_BOUND) { 1120984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson comparator.compare(from, from); 1121984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (toBound != NO_BOUND) { 1122984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson comparator.compare(to, to); 1123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1124984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1125984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.ascending = ascending; 1126984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.from = from; 1127984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.fromBound = fromBound; 1128984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.to = to; 1129984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.toBound = toBound; 1130984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1131984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1132984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public int size() { 1133984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return count(entrySet().iterator()); 1134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1136984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean isEmpty() { 11377cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return endpoint(true) == null; 1138f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1139984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1140984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public V get(Object key) { 1141984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds(key) ? TreeMap.this.get(key) : null; 1142f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1143f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1144984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean containsKey(Object key) { 1145984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds(key) && TreeMap.this.containsKey(key); 1146984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1148984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public V put(K key, V value) { 1149984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (!isInBounds(key)) { 11502f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson throw outOfBounds(key, fromBound, toBound); 1151f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1152984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return putInternal(key, value); 1153f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1155984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public V remove(Object key) { 1156984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds(key) ? TreeMap.this.remove(key) : null; 1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1158984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1159984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 1160984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns true if the key is in bounds. 1161984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1162984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // this method throws ClassCastExceptions! 1163984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private boolean isInBounds(Object key) { 1164984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds((K) key, fromBound, toBound); 1165984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1166984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1167984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 1168984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns true if the key is in bounds. Use this overload with 1169984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * NO_BOUND to skip bounds checking on either end. 1170984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1171984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private boolean isInBounds(K key, Bound fromBound, Bound toBound) { 1172984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (fromBound == INCLUSIVE) { 1173984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparator.compare(key, from) < 0) { 1174984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; // less than from 1175f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1176984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (fromBound == EXCLUSIVE) { 1177984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparator.compare(key, from) <= 0) { 1178984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; // less than or equal to from 1179f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1182984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (toBound == INCLUSIVE) { 1183984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparator.compare(key, to) > 0) { 1184984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; // greater than 'to' 1185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1186984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else if (toBound == EXCLUSIVE) { 1187984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (comparator.compare(key, to) >= 0) { 1188984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; // greater than or equal to 'to' 1189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1190984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1192984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return true; 1193984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1194f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1195984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 1196984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns the entry if it is in bounds, or null if it is out of bounds. 1197984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 11987cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe private Node<K, V> bound(Node<K, V> node, Bound fromBound, Bound toBound) { 1199984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return node != null && isInBounds(node.getKey(), fromBound, toBound) ? node : null; 1200984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1202984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1203984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Navigable methods. 1204984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1205984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1206984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> firstEntry() { 120759cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(endpoint(true)); 1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1209f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1210984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> pollFirstEntry() { 12117cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe Node<K, V> result = endpoint(true); 1212984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (result != null) { 1213984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(result); 1214984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 121559cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(result); 1216984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1217f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1218984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K firstKey() { 12197cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe Entry<K, V> entry = endpoint(true); 1220984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (entry == null) { 1221984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new NoSuchElementException(); 1222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1223984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry.getKey(); 1224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1226984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> lastEntry() { 122759cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(endpoint(false)); 1228984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1229f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1230984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> pollLastEntry() { 12317cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe Node<K, V> result = endpoint(false); 1232984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (result != null) { 1233984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson removeInternal(result); 1234984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 123559cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(result); 1236f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1237f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1238984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K lastKey() { 12397cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe Entry<K, V> entry = endpoint(false); 1240984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (entry == null) { 1241984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new NoSuchElementException(); 1242984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1243984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry.getKey(); 1244984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1245f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1246984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /** 1247984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * @param first true for the first element, false for the last. 1248984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 12497cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe private Node<K, V> endpoint(boolean first) { 12507cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe Node<K, V> node; 1251984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (ascending == first) { 1252984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson switch (fromBound) { 1253984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case NO_BOUND: 12547cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe node = root == null ? null : root.first(); 1255984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; 1256984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case INCLUSIVE: 12577cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe node = find(from, CEILING); 1258984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; 1259984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case EXCLUSIVE: 12607cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe node = find(from, HIGHER); 1261984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; 1262984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson default: 1263984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new AssertionError(); 1264f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 12657cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return bound(node, NO_BOUND, toBound); 1266984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } else { 1267984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson switch (toBound) { 1268984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case NO_BOUND: 12697cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe node = root == null ? null : root.last(); 1270984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; 1271984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case INCLUSIVE: 12727cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe node = find(to, FLOOR); 1273984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; 1274984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson case EXCLUSIVE: 12757cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe node = find(to, LOWER); 1276984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson break; 1277984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson default: 1278984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new AssertionError(); 1279f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 12807cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return bound(node, fromBound, NO_BOUND); 1281984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1282984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1283f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 12842f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson /** 12852f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * Performs a find on the underlying tree after constraining it to the 12862f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * bounds of this view. Examples: 12872f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * 12882f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * bound is (A..C) 12892f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * findBounded(B, FLOOR) stays source.find(B, FLOOR) 12902f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * 12912f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * bound is (A..C) 12922f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * findBounded(C, FLOOR) becomes source.find(C, LOWER) 12932f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * 12942f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * bound is (A..C) 12952f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * findBounded(D, LOWER) becomes source.find(C, LOWER) 12962f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * 12972f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * bound is (A..C] 12982f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * findBounded(D, FLOOR) becomes source.find(C, FLOOR) 12992f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * 13002f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * bound is (A..C] 13012f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * findBounded(D, LOWER) becomes source.find(C, FLOOR) 13022f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson */ 13032f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson private Entry<K, V> findBounded(K key, Relation relation) { 13042f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson relation = relation.forOrder(ascending); 13052f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Bound fromBoundForCheck = fromBound; 13062f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Bound toBoundForCheck = toBound; 13072f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson 13082f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (toBound != NO_BOUND && (relation == LOWER || relation == FLOOR)) { 13092f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson int comparison = comparator.compare(to, key); 13102f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (comparison <= 0) { 13112f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson key = to; 13122f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (toBound == EXCLUSIVE) { 13132f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson relation = LOWER; // 'to' is too high 13142f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } else if (comparison < 0) { 13152f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson relation = FLOOR; // we already went lower 13162f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 13172f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 13182f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson toBoundForCheck = NO_BOUND; // we've already checked the upper bound 13192f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 13202f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson 13212f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (fromBound != NO_BOUND && (relation == CEILING || relation == HIGHER)) { 13222f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson int comparison = comparator.compare(from, key); 13232f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (comparison >= 0) { 13242f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson key = from; 13252f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (fromBound == EXCLUSIVE) { 13262f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson relation = HIGHER; // 'from' is too low 13272f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } else if (comparison > 0) { 13282f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson relation = CEILING; // we already went higher 13292f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 13302f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 13312f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson fromBoundForCheck = NO_BOUND; // we've already checked the lower bound 13322f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 13332f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson 13342f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return bound(find(key, relation), fromBoundForCheck, toBoundForCheck); 13352f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 13362f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson 1337984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> lowerEntry(K key) { 133859cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(findBounded(key, LOWER)); 1339984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1340f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1341984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K lowerKey(K key) { 13422f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Entry<K, V> entry = findBounded(key, LOWER); 1343984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1344f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1345f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1346984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> floorEntry(K key) { 134759cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(findBounded(key, FLOOR)); 1348f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1349f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1350984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K floorKey(K key) { 13512f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Entry<K, V> entry = findBounded(key, FLOOR); 1352984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1353f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1354984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1355984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> ceilingEntry(K key) { 135659cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(findBounded(key, CEILING)); 1357f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1358f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1359984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K ceilingKey(K key) { 13602f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Entry<K, V> entry = findBounded(key, CEILING); 1361984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1362f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1363984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1364984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> higherEntry(K key) { 136559cb78e2355929587089ee436a0172af652d2aa5Jeremy Sharpe return immutableCopy(findBounded(key, HIGHER)); 1366f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1367f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1368984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K higherKey(K key) { 13692f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Entry<K, V> entry = findBounded(key, HIGHER); 1370984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1371f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1372984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1373984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Comparator<? super K> comparator() { 1374984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (ascending) { 1375984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return TreeMap.this.comparator(); 1376f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } else { 1377984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return Collections.reverseOrder(comparator); 1378f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1379f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1380f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1381984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1382984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * View factory methods. 1383984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1384984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1385984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private BoundedEntrySet entrySet; 1386984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private BoundedKeySet keySet; 1387984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1388984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Set<Entry<K, V>> entrySet() { 1389984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson BoundedEntrySet result = entrySet; 1390984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result != null ? result : (entrySet = new BoundedEntrySet()); 1391f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1392f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1393984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Set<K> keySet() { 1394984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return navigableKeySet(); 1395984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1396f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1397984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> navigableKeySet() { 1398984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson BoundedKeySet result = keySet; 1399984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result != null ? result : (keySet = new BoundedKeySet()); 1400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1401f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1402984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> descendingMap() { 1403984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(!ascending, from, fromBound, to, toBound); 1404984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1405f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1406984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> descendingKeySet() { 1407984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(!ascending, from, fromBound, to, toBound).navigableKeySet(); 1408984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1409f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1410984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive) { 1411984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound fromBound = fromInclusive ? INCLUSIVE : EXCLUSIVE; 1412984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound toBound = toInclusive ? INCLUSIVE : EXCLUSIVE; 1413984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(from, fromBound, to, toBound); 1414f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1415f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1416984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> subMap(K fromInclusive, K toExclusive) { 1417984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(fromInclusive, INCLUSIVE, toExclusive, EXCLUSIVE); 1418f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1419984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1420984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> headMap(K to, boolean inclusive) { 1421984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound toBound = inclusive ? INCLUSIVE : EXCLUSIVE; 1422984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(null, NO_BOUND, to, toBound); 1423f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1424f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1425984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> headMap(K toExclusive) { 1426984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(null, NO_BOUND, toExclusive, EXCLUSIVE); 1427984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1428f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1429984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> tailMap(K from, boolean inclusive) { 1430984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound fromBound = inclusive ? INCLUSIVE : EXCLUSIVE; 1431984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(from, fromBound, null, NO_BOUND); 1432f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1433984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1434984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableMap<K, V> tailMap(K fromInclusive) { 1435984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(fromInclusive, INCLUSIVE, null, NO_BOUND); 1436f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1437f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1438984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private NavigableMap<K, V> subMap(K from, Bound fromBound, K to, Bound toBound) { 1439984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (!ascending) { 1440984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson K fromTmp = from; 1441984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Bound fromBoundTmp = fromBound; 1442984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson from = to; 1443984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson fromBound = toBound; 1444984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson to = fromTmp; 1445984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson toBound = fromBoundTmp; 1446984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1447f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 14482f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson /* 14492f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * If both the current and requested bounds are exclusive, the isInBounds check must be 14502f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson * inclusive. For example, to create (C..F) from (A..F), the bound 'F' is in bounds. 14512f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson */ 14522f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson 1453984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (fromBound == NO_BOUND) { 1454984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson from = this.from; 1455984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson fromBound = this.fromBound; 14562f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } else { 14572f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Bound fromBoundToCheck = fromBound == this.fromBound ? INCLUSIVE : this.fromBound; 14582f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (!isInBounds(from, fromBoundToCheck, this.toBound)) { 14592f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson throw outOfBounds(to, fromBoundToCheck, this.toBound); 1460984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1461984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1462f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1463984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (toBound == NO_BOUND) { 1464984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson to = this.to; 1465984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson toBound = this.toBound; 14662f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } else { 14672f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson Bound toBoundToCheck = toBound == this.toBound ? INCLUSIVE : this.toBound; 14682f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson if (!isInBounds(to, this.fromBound, toBoundToCheck)) { 14692f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson throw outOfBounds(to, this.fromBound, toBoundToCheck); 1470984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1471984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1472984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1473984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(ascending, from, fromBound, to, toBound); 1474f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1475984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 14762f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson private IllegalArgumentException outOfBounds(Object value, Bound fromBound, Bound toBound) { 14772f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson return new IllegalArgumentException(value + " not in range " 14782f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson + fromBound.leftCap(from) + ".." + toBound.rightCap(to)); 14792f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson } 14802f2e06eeabb1c4b2064918f4aa041ba3a7fe7c67Jesse Wilson 1481984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1482984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Bounded view implementations. 1483984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1484984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1485984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson abstract class BoundedIterator<T> extends MapIterator<T> { 1486984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson protected BoundedIterator(Node<K, V> next) { 1487984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson super(next); 1488984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1489984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1490984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override protected Node<K, V> stepForward() { 1491984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> result = super.stepForward(); 1492984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (next != null && !isInBounds(next.key, NO_BOUND, toBound)) { 1493984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson next = null; 1494f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1495984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 1496984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1497984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1498984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override protected Node<K, V> stepBackward() { 1499984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Node<K, V> result = super.stepBackward(); 1500984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (next != null && !isInBounds(next.key, fromBound, NO_BOUND)) { 1501984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson next = null; 1502f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1503984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return result; 1504f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1505f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1506f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1507984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson final class BoundedEntrySet extends AbstractSet<Entry<K, V>> { 1508984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public int size() { 1509984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return BoundedMap.this.size(); 1510f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1511f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1512984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean isEmpty() { 1513984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return BoundedMap.this.isEmpty(); 1514f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1515f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1516984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Iterator<Entry<K, V>> iterator() { 15177cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return new BoundedIterator<Entry<K, V>>(endpoint(true)) { 1518984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Entry<K, V> next() { 1519984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return ascending ? stepForward() : stepBackward(); 1520984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1521984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson }; 1522984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1523984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1524984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean contains(Object o) { 1525984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (!(o instanceof Entry)) { 1526984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; 1527f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1528984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<?, ?> entry = (Entry<?, ?>) o; 1529984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds(entry.getKey()) && findByEntry(entry) != null; 1530f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1531f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1532984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean remove(Object o) { 1533984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson if (!(o instanceof Entry)) { 1534984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return false; 1535f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1536984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<?, ?> entry = (Entry<?, ?>) o; 1537984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds(entry.getKey()) && TreeMap.this.entrySet().remove(entry); 1538f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1539f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1540f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1541984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson final class BoundedKeySet extends AbstractSet<K> implements NavigableSet<K> { 1542984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public int size() { 1543984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return BoundedMap.this.size(); 1544984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1545984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1546984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean isEmpty() { 1547984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return BoundedMap.this.isEmpty(); 1548f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1549984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1550984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Iterator<K> iterator() { 15517cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return new BoundedIterator<K>(endpoint(true)) { 1552984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K next() { 1553984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return (ascending ? stepForward() : stepBackward()).key; 1554984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1555984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson }; 1556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1557984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1558984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Iterator<K> descendingIterator() { 15597cf7ec13b4e7e8f044c310e63dd0f6f9f58577d7Jeremy Sharpe return new BoundedIterator<K>(endpoint(false)) { 1560984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K next() { 1561984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return (ascending ? stepBackward() : stepForward()).key; 1562984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1563984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson }; 1564f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1565f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1566984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean contains(Object key) { 1567984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds(key) && findByObject(key) != null; 1568984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1569f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 1570984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public boolean remove(Object key) { 1571984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return isInBounds(key) && removeInternalByKey(key) != null; 1572984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1574984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1575984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Navigable methods. 1576984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1577984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1578984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K first() { 1579984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return firstKey(); 1580f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson } 1581984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1582984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K pollFirst() { 1583984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<K, ?> entry = pollFirstEntry(); 1584984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1587984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K last() { 1588984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return lastKey(); 1589984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1591984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K pollLast() { 1592984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Entry<K, ?> entry = pollLastEntry(); 1593984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return entry != null ? entry.getKey() : null; 1594984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1595984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1596984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K lower(K key) { 1597984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return lowerKey(key); 1598984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1599984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1600984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K floor(K key) { 1601984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return floorKey(key); 1602984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1603984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1604984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K ceiling(K key) { 1605984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return ceilingKey(key); 1606984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1607984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1608984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public K higher(K key) { 1609984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return higherKey(key); 1610984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1611984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1612984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public Comparator<? super K> comparator() { 1613984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return BoundedMap.this.comparator(); 1614984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1615984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1616984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1617984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * View factory methods. 1618984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson */ 1619984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1620984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> subSet(K from, boolean fromInclusive, K to, boolean toInclusive) { 1621984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(from, fromInclusive, to, toInclusive).navigableKeySet(); 1622984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1623984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1624984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedSet<K> subSet(K fromInclusive, K toExclusive) { 1625984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return subMap(fromInclusive, toExclusive).navigableKeySet(); 1626984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1627984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1628984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> headSet(K to, boolean inclusive) { 1629984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return headMap(to, inclusive).navigableKeySet(); 1630984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1631984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1632984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedSet<K> headSet(K toExclusive) { 1633984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return headMap(toExclusive).navigableKeySet(); 1634984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1635984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1636984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> tailSet(K from, boolean inclusive) { 1637984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return tailMap(from, inclusive).navigableKeySet(); 1638984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1639984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1640984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public SortedSet<K> tailSet(K fromInclusive) { 1641984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return tailMap(fromInclusive).navigableKeySet(); 1642984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1643984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1644984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson public NavigableSet<K> descendingSet() { 1645984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return new BoundedMap(!ascending, from, fromBound, to, toBound).navigableKeySet(); 1646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1649984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Object writeReplace() throws ObjectStreamException { 1650984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return ascending 1651984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson ? new AscendingSubMap<K, V>(TreeMap.this, from, fromBound, to, toBound) 1652984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson : new DescendingSubMap<K, V>(TreeMap.this, from, fromBound, to, toBound); 1653984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1654984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1657984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Returns the number of elements in the iteration. 1658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1659984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson static int count(Iterator<?> iterator) { 1660984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int count = 0; 1661984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson while (iterator.hasNext()) { 1662984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson iterator.next(); 1663984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson count++; 1664984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1665984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return count; 1666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1668984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson /* 1669984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson * Serialization 1670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1671984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1672984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private static final long serialVersionUID = 919286545866124006L; 1673984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1674984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private void writeObject(ObjectOutputStream stream) throws IOException { 1675984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson stream.putFields().put("comparator", comparator != NATURAL_ORDER ? comparator : null); 1676984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson stream.writeFields(); 1677984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson stream.writeInt(size); 1678984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson for (Map.Entry<K, V> entry : entrySet()) { 1679984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson stream.writeObject(entry.getKey()); 1680984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson stream.writeObject(entry.getValue()); 1681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1684984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // we have to trust that keys are Ks and values are Vs 1685984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 1686984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson GetField fields = stream.readFields(); 1687984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson comparator = (Comparator<? super K>) fields.get("comparator", null); 1688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (comparator == null) { 1689984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson comparator = (Comparator<? super K>) NATURAL_ORDER; 1690984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1691984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson int size = stream.readInt(); 1692984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson for (int i = 0; i < size; i++) { 1693984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson putInternal((K) stream.readObject(), (V) stream.readObject()); 1694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1697984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson static abstract class NavigableSubMap<K, V> extends AbstractMap<K, V> implements Serializable { 16980790403433525b7ca94391592d72b13a4c94578cJesse Wilson private static final long serialVersionUID = -2102997345730753016L; 1699984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson TreeMap<K, V> m; 1700984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Object lo; 1701984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Object hi; 1702984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean fromStart; 1703984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean toEnd; 1704984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean loInclusive; 1705984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean hiInclusive; 1706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1707984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson NavigableSubMap(TreeMap<K, V> delegate, K from, Bound fromBound, K to, Bound toBound) { 1708984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.m = delegate; 1709984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.lo = from; 1710984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.hi = to; 17110790403433525b7ca94391592d72b13a4c94578cJesse Wilson this.fromStart = fromBound == NO_BOUND; 17120790403433525b7ca94391592d72b13a4c94578cJesse Wilson this.toEnd = toBound == NO_BOUND; 1713984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.loInclusive = fromBound == INCLUSIVE; 1714984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson this.hiInclusive = toBound == INCLUSIVE; 1715984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1717984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Set<Entry<K, V>> entrySet() { 1718984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new UnsupportedOperationException(); 1719984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1721984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // we have to trust that the bounds are Ks 17220790403433525b7ca94391592d72b13a4c94578cJesse Wilson protected Object readResolve() throws ObjectStreamException { 17230790403433525b7ca94391592d72b13a4c94578cJesse Wilson Bound fromBound = fromStart ? NO_BOUND : (loInclusive ? INCLUSIVE : EXCLUSIVE); 17240790403433525b7ca94391592d72b13a4c94578cJesse Wilson Bound toBound = toEnd ? NO_BOUND : (hiInclusive ? INCLUSIVE : EXCLUSIVE); 1725984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean ascending = !(this instanceof DescendingSubMap); 1726984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson return m.new BoundedMap(ascending, (K) lo, fromBound, (K) hi, toBound); 1727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1730984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson static class DescendingSubMap<K, V> extends NavigableSubMap<K, V> { 1731984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private static final long serialVersionUID = 912986545866120460L; 1732984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson Comparator<K> reverseComparator; 1733984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson DescendingSubMap(TreeMap<K, V> delegate, K from, Bound fromBound, K to, Bound toBound) { 1734984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson super(delegate, from, fromBound, to, toBound); 1735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1738984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson static class AscendingSubMap<K, V> extends NavigableSubMap<K, V> { 1739984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private static final long serialVersionUID = 912986545866124060L; 1740984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson AscendingSubMap(TreeMap<K, V> delegate, K from, Bound fromBound, K to, Bound toBound) { 1741984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson super(delegate, from, fromBound, to, toBound); 1742984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1743984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1744984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 17450790403433525b7ca94391592d72b13a4c94578cJesse Wilson class SubMap extends AbstractMap<K, V> implements Serializable { 1746984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson private static final long serialVersionUID = -6520786458950516097L; 17470790403433525b7ca94391592d72b13a4c94578cJesse Wilson Object fromKey; 17480790403433525b7ca94391592d72b13a4c94578cJesse Wilson Object toKey; 1749984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean fromStart; 1750984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson boolean toEnd; 1751984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1752984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @Override public Set<Entry<K, V>> entrySet() { 1753984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson throw new UnsupportedOperationException(); 1754984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson } 1755984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson 1756984dc62f58d1f9611ebccc2598f714c15242a6ebJesse Wilson @SuppressWarnings("unchecked") // we have to trust that the bounds are Ks 17570790403433525b7ca94391592d72b13a4c94578cJesse Wilson protected Object readResolve() throws ObjectStreamException { 17580790403433525b7ca94391592d72b13a4c94578cJesse Wilson Bound fromBound = fromStart ? NO_BOUND : INCLUSIVE; 17590790403433525b7ca94391592d72b13a4c94578cJesse Wilson Bound toBound = toEnd ? NO_BOUND : EXCLUSIVE; 17600790403433525b7ca94391592d72b13a4c94578cJesse Wilson return new BoundedMap(true, (K) fromKey, fromBound, (K) toKey, toBound); 1761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1764