TreeMap与Map的关系如下图:

TreeMap介绍:
(1)TreeMap是一个有序的key-value集合,是通过红黑树来实现的。
(2)TreeMap是继承于AbstractMap,所以他是一个Map,是一个key-value集合。
(3)TreeMap实现了Navigable接口,支持一系列的导航方法,TreeMap是有序集合
(4)实现了Cloneable接口,可以被克隆
(5)TreeMap实现了Serializable接口,它支持序列化
(6)TreeMap基于红黑树数显,映射根据其键的自然排序进行排序
TreeMap主要的API:
Entry<> ceilingEntry(K key) K ceilingKey(K key) clear() Object clone() Comparator K> comparator() containsKey(Object key) NavigableSet<> descendingKeySet() NavigableMap<> descendingMap() Set<<>> entrySet() Entry<> firstEntry() K firstKey() Entry<> floorEntry(K key) K floorKey(K key) V get(Object key) NavigableMap<> headMap(K toinclusive) SortedMap<> headMap(K toExclusive) Entry<> higherEntry(K key) K higherKey(K key) isEmpty() Set<> keySet() Entry<> lastEntry() K lastKey() Entry<> lowerEntry(K key) K lowerKey(K key) NavigableSet<> navigableKeySet() Entry<> pollFirstEntry() Entry<> pollLastEntry() V put(K keyV value) V remove(Object key) size() SortedMap<> subMap(K fromInclusiveK toExclusive) NavigableMap<> subMap(K fromfromInclusiveK totoInclusive) NavigableMap<> tailMap(K frominclusive) SortedMap<> tailMap(K fromInclusive)
treemap遍历方式
(1)遍历TreeMap的键值对:根据entrySet()获取TreeMap的“键值对”集合,对键值对集合通过Iterator迭代遍历。
String key=Integer value=Iterator iterator=map.entrySet().iterator()(iterator.hasNext())
{
Map.Entry entry=(Map.Entry)iterator.next() key=(String) entry.getKey() value=(Integer)entry.getValue()}(2)遍历TreeMap的键:根据keySet()获得“键”集合,通过迭代器去遍历键集合。
String key = Integer integ = Iterator iter = map.keySet().iterator()(iter.hasNext()) {
key = (String)iter.next() integ = (Integer)map.get(key)}(3)遍历TreeMap的值:根据values获得值的集合,通过迭代器去遍历值的集合。
Integer value = Collection c = map.values()Iterator iter= c.iterator()(iter.hasNext())
{
value = (Integer)iter.next()}TreeMap示例代码:
Snowy(SnowyAdmin)是国内首个国密前后端分离快速开发平台,集成国密加解密插件, 软件层面完全符合等保测评要求,同时实现国产化机型、中间件、数据库适配,是您的不二之选! 技术框架与密码结合,让更多的人认识密码,使用密码;更是让前后分离“密”不可分。采用SpringBoot+MybatisPlus+AntDesignVue+Vite 等更多组件及前沿技术开发,注释丰富,代码简洁,开箱即用
public class Hello {
public static void main(String[] args) {
testTreeMapOridinaryAPIs();
testSubMapAPIs();
}
private static void testTreeMapOridinaryAPIs() {
// 初始化随机种子
Random r = new Random();
// 新建TreeMap
TreeMap tmap = new TreeMap();
// 添加操作
tmap.put("one", r.nextInt(10));
tmap.put("two", r.nextInt(10));
tmap.put("three", r.nextInt(10));
tmap.put("four", r.nextInt(10));
tmap.put("five", r.nextInt(10));
tmap.put("six", r.nextInt(10));
System.out.printf("\n ---- testTreeMapOridinaryAPIs ----\n");
// 打印出TreeMap
System.out.printf("%s\n",tmap );
// 通过Iterator遍历key-value
Iterator iter = tmap.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
System.out.printf("next : %s - %s\n", entry.getKey(), entry.getValue());
}
// TreeMap的键值对个数
System.out.printf("size: %s\n", tmap.size());
// containsKey(Object key) :是否包含键key
System.out.printf("contains key two : %s\n",tmap.containsKey("two"));
System.out.printf("contains key five : %s\n",tmap.containsKey("five"));
// containsValue(Object value) :是否包含值value
System.out.printf("contains value 0 : %s\n",tmap.containsValue(new Integer(0)));
// remove(Object key) : 删除键key对应的键值对
tmap.remove("three");
System.out.printf("tmap:%s\n",tmap );
// clear() : 清空TreeMap
tmap.clear();
// isEmpty() : TreeMap是否为空
System.out.printf("%s\n", (tmap.isEmpty()?"tmap is empty":"tmap is not empty") );
}
public static void testSubMapAPIs() {
// 新建TreeMap
TreeMap tmap = new TreeMap();
// 添加“键值对”
tmap.put("a", 101);
tmap.put("b", 102);
tmap.put("c", 103);
tmap.put("d", 104);
tmap.put("e", 105);
System.out.printf("\n ---- testSubMapAPIs ----\n");
// 打印出TreeMap
System.out.printf("tmap:\n\t%s\n", tmap);
// 测试 headMap(K toKey)
System.out.printf("tmap.headMap(\"c\"):\n\t%s\n", tmap.headMap("c"));
// 测试 headMap(K toKey, boolean inclusive)
System.out.printf("tmap.headMap(\"c\", true):\n\t%s\n", tmap.headMap("c", true));
System.out.printf("tmap.headMap(\"c\", false):\n\t%s\n", tmap.headMap("c", false));
// 测试 tailMap(K fromKey)
System.out.printf("tmap.tailMap(\"c\"):\n\t%s\n", tmap.tailMap("c"));
// 测试 tailMap(K fromKey, boolean inclusive)
System.out.printf("tmap.tailMap(\"c\", true):\n\t%s\n", tmap.tailMap("c", true));
System.out.printf("tmap.tailMap(\"c\", false):\n\t%s\n", tmap.tailMap("c", false));
// 测试 subMap(K fromKey, K toKey)
System.out.printf("tmap.subMap(\"a\", \"c\"):\n\t%s\n", tmap.subMap("a", "c"));
// 测试
System.out.printf("tmap.subMap(\"a\", true, \"c\", true):\n\t%s\n",
tmap.subMap("a", true, "c", true));
System.out.printf("tmap.subMap(\"a\", true, \"c\", false):\n\t%s\n",
tmap.subMap("a", true, "c", false));
System.out.printf("tmap.subMap(\"a\", false, \"c\", true):\n\t%s\n",
tmap.subMap("a", false, "c", true));
System.out.printf("tmap.subMap(\"a\", false, \"c\", false):\n\t%s\n",
tmap.subMap("a", false, "c", false));
// 测试 navigableKeySet()
System.out.printf("tmap.navigableKeySet():\n\t%s\n", tmap.navigableKeySet());
// 测试 descendingKeySet()
System.out.printf("tmap.descendingKeySet():\n\t%s\n", tmap.descendingKeySet());
}
public static void testNavigableMapAPIs() {
// 新建TreeMap
NavigableMap nav = new TreeMap();
// 添加“键值对”
nav.put("aaa", 111);
nav.put("bbb", 222);
nav.put("eee", 333);
nav.put("ccc", 555);
nav.put("ddd", 444);
System.out.printf("\n ---- testNavigableMapAPIs ----\n");
// 打印出TreeMap
System.out.printf("Whole list:%s%n", nav);
// 获取第一个key、第一个Entry
System.out.printf("First key: %s\tFirst entry: %s%n",nav.firstKey(), nav.firstEntry());
// 获取最后一个key、最后一个Entry
System.out.printf("Last key: %s\tLast entry: %s%n",nav.lastKey(), nav.lastEntry());
// 获取“小于/等于bbb”的最大键值对
System.out.printf("Key floor before bbb: %s%n",nav.floorKey("bbb"));
// 获取“小于bbb”的最大键值对
System.out.printf("Key lower before bbb: %s%n", nav.lowerKey("bbb"));
// 获取“大于/等于bbb”的最小键值对
System.out.printf("Key ceiling after ccc: %s%n",nav.ceilingKey("ccc"));
// 获取“大于bbb”的最小键值对
System.out.printf("Key higher after ccc: %s%n\n",nav.higherKey("ccc"));
}
}运行结果:
---- testTreeMapOridinaryAPIs ----
{five=5, four=5, one=3, six=8, three=1, two=0}
next : five - 5
next : four - 5
next : one - 3
next : six - 8
next : three - 1
next : two - 0
size: 6
contains key two : true
contains key five : true
contains value 0 : true
tmap:{five=5, four=5, one=3, six=8, two=0}
tmap is empty
---- testSubMapAPIs ----
tmap:
{a=101, b=102, c=103, d=104, e=105}
tmap.headMap("c"):
{a=101, b=102}
tmap.headMap("c", true):
{a=101, b=102, c=103}
tmap.headMap("c", false):
{a=101, b=102}
tmap.tailMap("c"):
{c=103, d=104, e=105}
tmap.tailMap("c", true):
{c=103, d=104, e=105}
tmap.tailMap("c", false):
{d=104, e=105}
tmap.subMap("a", "c"):
{a=101, b=102}
tmap.subMap("a", true, "c", true):
{a=101, b=102, c=103}
tmap.subMap("a", true, "c", false):
{a=101, b=102}
tmap.subMap("a", false, "c", true):
{b=102, c=103}
tmap.subMap("a", false, "c", false):
{b=102}
tmap.navigableKeySet():
[a, b, c, d, e]
tmap.descendingKeySet():
[e, d, c, b, a]基于Java8的SortedMap接口源代码:
public interface SortedMapextends Map { Comparator super K> comparator(); SortedMap subMap(K fromKey, K toKey); SortedMap headMap(K toKey); SortedMap tailMap(K fromKey); K firstKey(); K lastKey(); Set keySet(); Collection values(); Set > entrySet(); }
基于Java8的Navigable接口源代码:
public interface NavigableMapextends SortedMap { Map.Entry lowerEntry(K key); K lowerKey(K key); Map.Entry floorEntry(K key); K floorKey(K key); Map.Entry ceilingEntry(K key); K ceilingKey(K key); Map.Entry higherEntry(K key); K higherKey(K key); Map.Entry firstEntry(); Map.Entry lastEntry(); Map.Entry pollFirstEntry(); Map.Entry pollLastEntry(); NavigableMap descendingMap(); NavigableSet navigableKeySet(); NavigableSet descendingKeySet(); NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive); NavigableMap headMap(K toKey, boolean inclusive); NavigableMap tailMap(K fromKey, boolean inclusive); SortedMap subMap(K fromKey, K toKey); SortedMap headMap(K toKey); SortedMap tailMap(K fromKey); }
基于Java8的TreeMap源代码:
public class TreeMapextends AbstractMap implements NavigableMap , Cloneable, java.io.Serializable { private final Comparator super K> comparator;//比较器 private transient Entry root;//根节点 private transient int size = 0;//起始个数 private transient int modCount = 0;//tree改变次数 public TreeMap() { comparator = null; } public TreeMap(Comparator super K> comparator) { this.comparator = comparator; } public TreeMap(Map extends K, ? extends V> m) { comparator = null; putAll(m); } public TreeMap(SortedMap m) { comparator = m.comparator(); try { buildFromSorted(m.size(), m.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } } //获得个数 public int size() { return size; } //是否含有某个key public boolean containsKey(Object key) { return getEntry(key) != null; } //是否还有某个值 public boolean containsValue(Object value) { for (Entry e = getFirstEntry(); e != null; e = successor(e)) if (valEquals(value, e.value)) return true; return false; } //通过key获得值 public V get(Object key) { Entry p = getEntry(key); return (p==null ? null : p.value); } //比较器 public Comparator super K> comparator() { return comparator; } //获得第一个key public K firstKey() { return key(getFirstEntry()); } //获得最后一个key public K lastKey() { return key(getLastEntry()); } /** * Copies all of the mappings from the specified map to this map. * These mappings replace any mappings that this map had for any * of the keys currently in the specified map. * * @param map mappings to be stored in this map * @throws ClassCastException if the class of a key or value in * the specified map prevents it from being stored in this map * @throws NullPointerException if the specified map is null or * the specified map contains a null key and this map does not * permit null keys */ //拷贝某个特定的map到这个map public void putAll(Map extends K, ? extends V> map) { int mapSize = map.size(); if (size==0 && mapSize!=0 && map instanceof SortedMap) { Comparator> c = ((SortedMap,?>)map).comparator(); if (c == comparator || (c != null && c.equals(comparator))) { ++modCount; try { buildFromSorted(mapSize, map.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } return; } } super.putAll(map); } /** * Returns this map's entry for the given key, or {@code null} if the map * does not contain an entry for the key. * * @return this map's entry for the given key, or {@code null} if the map * does not contain an entry for the key * @throws ClassCastException if the specified key cannot be compared * with the keys currently in the map * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys */ //根据某个key获得entry final Entry getEntry(Object key) { // Offload comparator-based version for sake of performance if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") Comparable super K> k = (Comparable super K>) key; Entry p = root; while (p != null) { int cmp = k.compareTo(p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } return null; } /** * Version of getEntry using comparator. Split off from getEntry * for performance. (This is not worth doing for most methods, * that are less dependent on comparator performance, but is * worthwhile here.) */ //通过比较器来比较key,返回entry final Entry getEntryUsingComparator(Object key) { @SuppressWarnings("unchecked") K k = (K) key; Comparator super K> cpr = comparator; if (cpr != null) { Entry p = root; while (p != null) { int cmp = cpr.compare(k, p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } } return null; } /** * Gets the entry corresponding to the specified key; if no such entry * exists, returns the entry for the least key greater than the specified * key; if no such entry exists (i.e., the greatest key in the Tree is less * than the specified key), returns {@code null}. */ //获得与key关系最近的entry,上限 final Entry getCeilingEntry(K key) { Entry p = root; while (p != null) { int cmp = compare(key, p.key); if (cmp < 0) { if (p.left != null) p = p.left; else return p; } else if (cmp > 0) { if (p.right != null) { p = p.right; } else { Entry parent = p.parent; Entry ch = p; while (parent != null && ch == parent.right) { ch = parent; parent = parent.parent; } return parent; } } else return p; } return null; } /** * Gets the entry corresponding to the specified key; if no such entry * exists, returns the entry for the greatest key less than the specified * key; if no such entry exists, returns {@code null}. */ //获得与key关系最近的entry,下限 final Entry getFloorEntry(K key) { Entry p = root; while (p != null) { int cmp = compare(key, p.key); if (cmp > 0) { if (p.right != null) p = p.right; else return p; } else if (cmp < 0) { if (p.left != null) { p = p.left; } else { Entry parent = p.parent; Entry ch = p; while (parent != null && ch == parent.left) { ch = parent; parent = parent.parent; } return parent; } } else return p; } return null; } /** * Gets the entry for the least key greater than the specified * key; if no such entry exists, returns the entry for the least * key greater than the specified key; if no such entry exists * returns {@code null}. */ //比某个key大的entry final Entry getHigherEntry(K key) { Entry p = root; while (p != null) { int cmp = compare(key, p.key); if (cmp < 0) { if (p.left != null) p = p.left; else return p; } else { if (p.right != null) { p = p.right; } else { Entry parent = p.parent; Entry ch = p; while (parent != null && ch == parent.right) { ch = parent; parent = parent.parent; } return parent; } } } return null; } /** * Returns the entry for the greatest key less than the specified key; if * no such entry exists (i.e., the least key in the Tree is greater than * the specified key), returns {@code null}. */ //获得某个key小于最接近的entry final Entry getLowerEntry(K key) { Entry p = root; while (p != null) { int cmp = compare(key, p.key); if (cmp > 0) { if (p.right != null) p = p.right; else return p; } else { if (p.left != null) { p = p.left; } else { Entry parent = p.parent; Entry ch = p; while (parent != null && ch == parent.left) { ch = parent; parent = parent.parent; } return parent; } } } return null; } /** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * * @return the previous value associated with {@code key}, or * {@code null} if there was no mapping for {@code key}. * (A {@code null} return can also indicate that the map * previously associated {@code null} with {@code key}.) * @throws ClassCastException if the specified key cannot be compared * with the keys currently in the map * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys */ //插入key-value值 public V put(K key, V value) { Entry t = root; if (t == null) { compare(key, key); // type (and possibly null) check root = new Entry<>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry parent; // split comparator and comparable paths Comparator super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else { if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") Comparable super K> k = (Comparable super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } Entry e = new Entry<>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size++; modCount++; return null; } /** * Removes the mapping for this key from this TreeMap if present. * * @param key key for which mapping should be removed * @return the previous value associated with {@code key}, or * {@code null} if there was no mapping for {@code key}. * (A {@code null} return can also indicate that the map * previously associated {@code null} with {@code key}.) * @throws ClassCastException if the specified key cannot be compared * with the keys currently in the map * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys */ //删掉某个key,并返回value public V remove(Object key) { Entry p = getEntry(key); if (p == null) return null; V oldValue = p.value; deleteEntry(p); return oldValue; } /** * Removes all of the mappings from this map. * The map will be empty after this call returns. */ //清空 public void clear() { modCount++; size = 0; root = null; } /** * Returns a shallow copy of this {@code TreeMap} instance. (The keys and * values themselves are not cloned.) * * @return a shallow copy of this map */ //进行克隆,深拷贝 public Object clone() { TreeMap,?> clone; try { clone = (TreeMap,?>) super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e); } // Put clone into "virgin" state (except for comparator) clone.root = null; clone.size = 0; clone.modCount = 0; clone.entrySet = null; clone.navigableKeySet = null; clone.descendingMap = null; // Initialize clone with our mappings try { clone.buildFromSorted(size, entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } return clone; } // NavigableMap API methods /** * @since 1.6 */ //获得第一个entry public Map.Entry firstEntry() { return exportEntry(getFirstEntry()); } /** * @since 1.6 */ //最后一个entry public Map.Entry lastEntry() { return exportEntry(getLastEntry()); } /** * @since 1.6 */ //弹出第一个entry,并删除 public Map.Entry pollFirstEntry() { Entry p = getFirstEntry(); Map.Entry result = exportEntry(p); if (p != null) deleteEntry(p); return result; } /** * @since 1.6 */ //弹出最后一个entry,并删除 public Map.Entry pollLastEntry() { Entry p = getLastEntry(); Map.Entry result = exportEntry(p); if (p != null) deleteEntry(p); return result; } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public Map.Entry lowerEntry(K key) { return exportEntry(getLowerEntry(key)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public K lowerKey(K key) { return keyOrNull(getLowerEntry(key)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public Map.Entry floorEntry(K key) { return exportEntry(getFloorEntry(key)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public K floorKey(K key) { return keyOrNull(getFloorEntry(key)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public Map.Entry ceilingEntry(K key) { return exportEntry(getCeilingEntry(key)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public K ceilingKey(K key) { return keyOrNull(getCeilingEntry(key)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public Map.Entry higherEntry(K key) { return exportEntry(getHigherEntry(key)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if the specified key is null * and this map uses natural ordering, or its comparator * does not permit null keys * @since 1.6 */ public K higherKey(K key) { return keyOrNull(getHigherEntry(key)); } // Views /** * Fields initialized to contain an instance of the entry set view * the first time this view is requested. Views are stateless, so * there's no reason to create more than one. */ private transient EntrySet entrySet; private transient KeySet navigableKeySet; private transient NavigableMap descendingMap; /** * Returns a {@link Set} view of the keys contained in this map. * * The set's iterator returns the keys in ascending order. * The set's spliterator is * late-binding, * fail-fast, and additionally reports {@link Spliterator#SORTED} * and {@link Spliterator#ORDERED} with an encounter order that is ascending * key order. The spliterator's comparator (see * {@link java.util.Spliterator#getComparator()}) is {@code null} if * the tree map's comparator (see {@link #comparator()}) is {@code null}. * Otherwise, the spliterator's comparator is the same as or imposes the * same total ordering as the tree map's comparator. * *
The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through * the iterator's own {@code remove} operation), the results of * the iteration are undefined. The set supports element removal, * which removes the corresponding mapping from the map, via the * {@code Iterator.remove}, {@code Set.remove}, * {@code removeAll}, {@code retainAll}, and {@code clear} * operations. It does not support the {@code add} or {@code addAll} * operations. */ public Set
keySet() { return navigableKeySet(); } /** * @since 1.6 */ public NavigableSet navigableKeySet() { KeySet nks = navigableKeySet; return (nks != null) ? nks : (navigableKeySet = new KeySet<>(this)); } /** * @since 1.6 */ public NavigableSet descendingKeySet() { return descendingMap().navigableKeySet(); } /** * Returns a {@link Collection} view of the values contained in this map. * * The collection's iterator returns the values in ascending order * of the corresponding keys. The collection's spliterator is * late-binding, * fail-fast, and additionally reports {@link Spliterator#ORDERED} * with an encounter order that is ascending order of the corresponding * keys. * *
The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. If the map is * modified while an iteration over the collection is in progress * (except through the iterator's own {@code remove} operation), * the results of the iteration are undefined. The collection * supports element removal, which removes the corresponding * mapping from the map, via the {@code Iterator.remove}, * {@code Collection.remove}, {@code removeAll}, * {@code retainAll} and {@code clear} operations. It does not * support the {@code add} or {@code addAll} operations. */ public Collection
values() { Collection vs = values; return (vs != null) ? vs : (values = new Values()); } /** * Returns a {@link Set} view of the mappings contained in this map. * * The set's iterator returns the entries in ascending key order. The * sets's spliterator is * late-binding, * fail-fast, and additionally reports {@link Spliterator#SORTED} and * {@link Spliterator#ORDERED} with an encounter order that is ascending key * order. * *
The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. If the map is modified * while an iteration over the set is in progress (except through * the iterator's own {@code remove} operation, or through the * {@code setValue} operation on a map entry returned by the * iterator) the results of the iteration are undefined. The set * supports element removal, which removes the corresponding * mapping from the map, via the {@code Iterator.remove}, * {@code Set.remove}, {@code removeAll}, {@code retainAll} and * {@code clear} operations. It does not support the * {@code add} or {@code addAll} operations. */ public Set
> entrySet() { EntrySet es = entrySet; return (es != null) ? es : (entrySet = new EntrySet()); } /** * @since 1.6 */ public NavigableMap descendingMap() { NavigableMap km = descendingMap; return (km != null) ? km : (descendingMap = new DescendingSubMap<>(this, true, null, true, true, null, true)); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if {@code fromKey} or {@code toKey} is * null and this map uses natural ordering, or its comparator * does not permit null keys * @throws IllegalArgumentException {@inheritDoc} * @since 1.6 */ public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { return new AscendingSubMap<>(this, false, fromKey, fromInclusive, false, toKey, toInclusive); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if {@code toKey} is null * and this map uses natural ordering, or its comparator * does not permit null keys * @throws IllegalArgumentException {@inheritDoc} * @since 1.6 */ public NavigableMap headMap(K toKey, boolean inclusive) { return new AscendingSubMap<>(this, true, null, true, false, toKey, inclusive); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if {@code fromKey} is null * and this map uses natural ordering, or its comparator * does not permit null keys * @throws IllegalArgumentException {@inheritDoc} * @since 1.6 */ public NavigableMap tailMap(K fromKey, boolean inclusive) { return new AscendingSubMap<>(this, false, fromKey, inclusive, true, null, true); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if {@code fromKey} or {@code toKey} is * null and this map uses natural ordering, or its comparator * does not permit null keys * @throws IllegalArgumentException {@inheritDoc} */ public SortedMap subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if {@code toKey} is null * and this map uses natural ordering, or its comparator * does not permit null keys * @throws IllegalArgumentException {@inheritDoc} */ public SortedMap headMap(K toKey) { return headMap(toKey, false); } /** * @throws ClassCastException {@inheritDoc} * @throws NullPointerException if {@code fromKey} is null * and this map uses natural ordering, or its comparator * does not permit null keys * @throws IllegalArgumentException {@inheritDoc} */ public SortedMap tailMap(K fromKey) { return tailMap(fromKey, true); } @Override public boolean replace(K key, V oldValue, V newValue) { Entry p = getEntry(key); if (p!=null && Objects.equals(oldValue, p.value)) { p.value = newValue; return true; } return false; } @Override public V replace(K key, V value) { Entry p = getEntry(key); if (p!=null) { V oldValue = p.value; p.value = value; return oldValue; } return null; } @Override public void forEach(BiConsumer super K, ? super V> action) { Objects.requireNonNull(action); int expectedModCount = modCount; for (Entry e = getFirstEntry(); e != null; e = successor(e)) { action.accept(e.key, e.value); if (expectedModCount != modCount) { throw new ConcurrentModificationException(); } } } @Override public void replaceAll(BiFunction super K, ? super V, ? extends V> function) { Objects.requireNonNull(function); int expectedModCount = modCount; for (Entry e = getFirstEntry(); e != null; e = successor(e)) { e.value = function.apply(e.key, e.value); if (expectedModCount != modCount) { throw new ConcurrentModificationException(); } } } // View class support class Values extends AbstractCollection { public Iterator iterator() { return new ValueIterator(getFirstEntry()); } public int size() { return TreeMap.this.size(); } public boolean contains(Object o) { return TreeMap.this.containsValue(o); } public boolean remove(Object o) { for (Entry e = getFirstEntry(); e != null; e = successor(e)) { if (valEquals(e.getValue(), o)) { deleteEntry(e); return true; } } return false; } public void clear() { TreeMap.this.clear(); } public Spliterator spliterator() { return new ValueSpliterator (TreeMap.this, null, null, 0, -1, 0); } } class EntrySet extends AbstractSet > { public Iterator > iterator() { return new EntryIterator(getFirstEntry()); } public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry,?> entry = (Map.Entry,?>) o; Object value = entry.getValue(); Entry p = getEntry(entry.getKey()); return p != null && valEquals(p.getValue(), value); } public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry,?> entry = (Map.Entry,?>) o; Object value = entry.getValue(); Entry p = getEntry(entry.getKey()); if (p != null && valEquals(p.getValue(), value)) { deleteEntry(p); return true; } return false; } public int size() { return TreeMap.this.size(); } public void clear() { TreeMap.this.clear(); } public Spliterator > spliterator() { return new EntrySpliterator (TreeMap.this, null, null, 0, -1, 0); } } /* * Unlike Values and EntrySet, the KeySet class is static, * delegating to a NavigableMap to allow use by SubMaps, which * outweighs the ugliness of needing type-tests for the following * Iterator methods that are defined appropriately in main versus * submap classes. */ Iterator keyIterator() { return new KeyIterator(getFirstEntry()); } Iterator descendingKeyIterator() { return new DescendingKeyIterator(getLastEntry()); } static final class KeySet extends AbstractSet implements NavigableSet { private final NavigableMap m; KeySet(NavigableMap map) { m = map; } public Iterator iterator() { if (m instanceof TreeMap) return ((TreeMap )m).keyIterator(); else return ((TreeMap.NavigableSubMap )m).keyIterator(); } public Iterator descendingIterator() { if (m instanceof TreeMap) return ((TreeMap )m).descendingKeyIterator(); else return ((TreeMap.NavigableSubMap )m).descendingKeyIterator(); } public int size() { return m.size(); } public boolean isEmpty() { return m.isEmpty(); } public boolean contains(Object o) { return m.containsKey(o); } public void clear() { m.clear(); } public E lower(E e) { return m.lowerKey(e); } public E floor(E e) { return m.floorKey(e); } public E ceiling(E e) { return m.ceilingKey(e); } public E higher(E e) { return m.higherKey(e); } public E first() { return m.firstKey(); } public E last() { return m.lastKey(); } public Comparator super E> comparator() { return m.comparator(); } public E pollFirst() { Map.Entry e = m.pollFirstEntry(); return (e == null) ? null : e.getKey(); } public E pollLast() { Map.Entry e = m.pollLastEntry(); return (e == null) ? null : e.getKey(); } public boolean remove(Object o) { int oldSize = size(); m.remove(o); return size() != oldSize; } public NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { return new KeySet<>(m.subMap(fromElement, fromInclusive, toElement, toInclusive)); } public NavigableSet headSet(E toElement, boolean inclusive) { return new KeySet<>(m.headMap(toElement, inclusive)); } public NavigableSet tailSet(E fromElement, boolean inclusive) { return new KeySet<>(m.tailMap(fromElement, inclusive)); } public SortedSet subSet(E fromElement, E toElement) { return subSet(fromElement, true, toElement, false); } public SortedSet headSet(E toElement) { return headSet(toElement, false); } public SortedSet tailSet(E fromElement) { return tailSet(fromElement, true); } public NavigableSet descendingSet() { return new KeySet<>(m.descendingMap()); } public Spliterator spliterator() { return keySpliteratorFor(m); } } /** * Base class for TreeMap Iterators */ abstract class PrivateEntryIterator implements Iterator { Entry next; Entry lastReturned; int expectedModCount; PrivateEntryIterator(Entry first) { expectedModCount = modCount; lastReturned = null; next = first; } public final boolean hasNext() { return next != null; } final Entry nextEntry() { Entry e = next; if (e == null) throw new NoSuchElementException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); next = successor(e); lastReturned = e; return e; } final Entry prevEntry() { Entry e = next; if (e == null) throw new NoSuchElementException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); next = predecessor(e); lastReturned = e; return e; } public void remove() { if (lastReturned == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); // deleted entries are replaced by their successors if (lastReturned.left != null && lastReturned.right != null) next = lastReturned; deleteEntry(lastReturned); expectedModCount = modCount; lastReturned = null; } } final class EntryIterator extends PrivateEntryIterator > { EntryIterator(Entry first) { super(first); } public Map.Entry next() { return nextEntry(); } } final class ValueIterator extends PrivateEntryIterator { ValueIterator(Entry first) { super(first); } public V next() { return nextEntry().value; } } final class KeyIterator extends PrivateEntryIterator { KeyIterator(Entry first) { super(first); } public K next() { return nextEntry().key; } } final class DescendingKeyIterator extends PrivateEntryIterator { DescendingKeyIterator(Entry first) { super(first); } public K next() { return prevEntry().key; } public void remove() { if (lastReturned == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); deleteEntry(lastReturned); lastReturned = null; expectedModCount = modCount; } } // Little utilities /** * Compares two keys using the correct comparison method for this TreeMap. */ @SuppressWarnings("unchecked") final int compare(Object k1, Object k2) { return comparator==null ? ((Comparable super K>)k1).compareTo((K)k2) : comparator.compare((K)k1, (K)k2); } /** * Test two values for equality. Differs from o1.equals(o2) only in * that it copes with {@code null} o1 properly. */ static final boolean valEquals(Object o1, Object o2) { return (o1==null ? o2==null : o1.equals(o2)); } /** * Return SimpleImmutableEntry for entry, or null if null */ static Map.Entry exportEntry(TreeMap.Entry e) { return (e == null) ? null : new AbstractMap.SimpleImmutableEntry<>(e); } /** * Return key for entry, or null if null */ static K keyOrNull(TreeMap.Entry e) { return (e == null) ? null : e.key; } /** * Returns the key corresponding to the specified Entry. * @throws NoSuchElementException if the Entry is null */ static K key(Entry e) { if (e==null) throw new NoSuchElementException(); return e.key; } // SubMaps /** * Dummy value serving as unmatchable fence key for unbounded * SubMapIterators */ private static final Object UNBOUNDED = new Object(); /** * @serial include */ abstract static class NavigableSubMap extends AbstractMap implements NavigableMap , java.io.Serializable { private static final long serialVersionUID = -2102997345730753016L; /** * The backing map. */ final TreeMap m; /** * Endpoints are represented as triples (fromStart, lo, * loInclusive) and (toEnd, hi, hiInclusive). If fromStart is * true, then the low (absolute) bound is the start of the * backing map, and the other values are ignored. Otherwise, * if loInclusive is true, lo is the inclusive bound, else lo * is the exclusive bound. Similarly for the upper bound. */ final K lo, hi; final boolean fromStart, toEnd; final boolean loInclusive, hiInclusive; NavigableSubMap(TreeMap m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { if (!fromStart && !toEnd) { if (m.compare(lo, hi) > 0) throw new IllegalArgumentException("fromKey > toKey"); } else { if (!fromStart) // type check m.compare(lo, lo); if (!toEnd) m.compare(hi, hi); } this.m = m; this.fromStart = fromStart; this.lo = lo; this.loInclusive = loInclusive; this.toEnd = toEnd; this.hi = hi; this.hiInclusive = hiInclusive; } // internal utilities final boolean tooLow(Object key) { if (!fromStart) { int c = m.compare(key, lo); if (c < 0 || (c == 0 && !loInclusive)) return true; } return false; } final boolean tooHigh(Object key) { if (!toEnd) { int c = m.compare(key, hi); if (c > 0 || (c == 0 && !hiInclusive)) return true; } return false; } final boolean inRange(Object key) { return !tooLow(key) && !tooHigh(key); } final boolean inClosedRange(Object key) { return (fromStart || m.compare(key, lo) >= 0) && (toEnd || m.compare(hi, key) >= 0); } final boolean inRange(Object key, boolean inclusive) { return inclusive ? inRange(key) : inClosedRange(key); } /* * Absolute versions of relation operations. * Subclasses map to these using like-named "sub" * versions that invert senses for descending maps */ final TreeMap.Entry absLowest() { TreeMap.Entry e = (fromStart ? m.getFirstEntry() : (loInclusive ? m.getCeilingEntry(lo) : m.getHigherEntry(lo))); return (e == null || tooHigh(e.key)) ? null : e; } final TreeMap.Entry absHighest() { TreeMap.Entry e = (toEnd ? m.getLastEntry() : (hiInclusive ? m.getFloorEntry(hi) : m.getLowerEntry(hi))); return (e == null || tooLow(e.key)) ? null : e; } final TreeMap.Entry absCeiling(K key) { if (tooLow(key)) return absLowest(); TreeMap.Entry e = m.getCeilingEntry(key); return (e == null || tooHigh(e.key)) ? null : e; } final TreeMap.Entry absHigher(K key) { if (tooLow(key)) return absLowest(); TreeMap.Entry e = m.getHigherEntry(key); return (e == null || tooHigh(e.key)) ? null : e; } final TreeMap.Entry absFloor(K key) { if (tooHigh(key)) return absHighest(); TreeMap.Entry e = m.getFloorEntry(key); return (e == null || tooLow(e.key)) ? null : e; } final TreeMap.Entry absLower(K key) { if (tooHigh(key)) return absHighest(); TreeMap.Entry e = m.getLowerEntry(key); return (e == null || tooLow(e.key)) ? null : e; } /** Returns the absolute high fence for ascending traversal */ final TreeMap.Entry absHighFence() { return (toEnd ? null : (hiInclusive ? m.getHigherEntry(hi) : m.getCeilingEntry(hi))); } /** Return the absolute low fence for descending traversal */ final TreeMap.Entry absLowFence() { return (fromStart ? null : (loInclusive ? m.getLowerEntry(lo) : m.getFloorEntry(lo))); } // Abstract methods defined in ascending vs descending classes // These relay to the appropriate absolute versions abstract TreeMap.Entry subLowest(); abstract TreeMap.Entry subHighest(); abstract TreeMap.Entry subCeiling(K key); abstract TreeMap.Entry subHigher(K key); abstract TreeMap.Entry subFloor(K key); abstract TreeMap.Entry subLower(K key); /** Returns ascending iterator from the perspective of this submap */ abstract Iterator keyIterator(); abstract Spliterator keySpliterator(); /** Returns descending iterator from the perspective of this submap */ abstract Iterator descendingKeyIterator(); // public methods public boolean isEmpty() { return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty(); } public int size() { return (fromStart && toEnd) ? m.size() : entrySet().size(); } public final boolean containsKey(Object key) { return inRange(key) && m.containsKey(key); } public final V put(K key, V value) { if (!inRange(key)) throw new IllegalArgumentException("key out of range"); return m.put(key, value); } public final V get(Object key) { return !inRange(key) ? null : m.get(key); } public final V remove(Object key) { return !inRange(key) ? null : m.remove(key); } public final Map.Entry ceilingEntry(K key) { return exportEntry(subCeiling(key)); } public final K ceilingKey(K key) { return keyOrNull(subCeiling(key)); } public final Map.Entry higherEntry(K key) { return exportEntry(subHigher(key)); } public final K higherKey(K key) { return keyOrNull(subHigher(key)); } public final Map.Entry floorEntry(K key) { return exportEntry(subFloor(key)); } public final K floorKey(K key) { return keyOrNull(subFloor(key)); } public final Map.Entry lowerEntry(K key) { return exportEntry(subLower(key)); } public final K lowerKey(K key) { return keyOrNull(subLower(key)); } public final K firstKey() { return key(subLowest()); } public final K lastKey() { return key(subHighest()); } public final Map.Entry firstEntry() { return exportEntry(subLowest()); } public final Map.Entry lastEntry() { return exportEntry(subHighest()); } public final Map.Entry pollFirstEntry() { TreeMap.Entry e = subLowest(); Map.Entry result = exportEntry(e); if (e != null) m.deleteEntry(e); return result; } public final Map.Entry pollLastEntry() { TreeMap.Entry e = subHighest(); Map.Entry result = exportEntry(e); if (e != null) m.deleteEntry(e); return result; } // Views transient NavigableMap descendingMapView; transient EntrySetView entrySetView; transient KeySet navigableKeySetView; public final NavigableSet navigableKeySet() { KeySet nksv = navigableKeySetView; return (nksv != null) ? nksv : (navigableKeySetView = new TreeMap.KeySet<>(this)); } public final Set keySet() { return navigableKeySet(); } public NavigableSet descendingKeySet() { return descendingMap().navigableKeySet(); } public final SortedMap subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); } public final SortedMap headMap(K toKey) { return headMap(toKey, false); } public final SortedMap tailMap(K fromKey) { return tailMap(fromKey, true); } // View classes abstract class EntrySetView extends AbstractSet > { private transient int size = -1, sizeModCount; public int size() { if (fromStart && toEnd) return m.size(); if (size == -1 || sizeModCount != m.modCount) { sizeModCount = m.modCount; size = 0; Iterator> i = iterator(); while (i.hasNext()) { size++; i.next(); } } return size; } public boolean isEmpty() { TreeMap.Entry n = absLowest(); return n == null || tooHigh(n.key); } public boolean contains(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry,?> entry = (Map.Entry,?>) o; Object key = entry.getKey(); if (!inRange(key)) return false; TreeMap.Entry,?> node = m.getEntry(key); return node != null && valEquals(node.getValue(), entry.getValue()); } public boolean remove(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry,?> entry = (Map.Entry,?>) o; Object key = entry.getKey(); if (!inRange(key)) return false; TreeMap.Entry node = m.getEntry(key); if (node!=null && valEquals(node.getValue(), entry.getValue())) { m.deleteEntry(node); return true; } return false; } } /** * Iterators for SubMaps */ abstract class SubMapIterator implements Iterator { TreeMap.Entry lastReturned; TreeMap.Entry next; final Object fenceKey; int expectedModCount; SubMapIterator(TreeMap.Entry first, TreeMap.Entry fence) { expectedModCount = m.modCount; lastReturned = null; next = first; fenceKey = fence == null ? UNBOUNDED : fence.key; } public final boolean hasNext() { return next != null && next.key != fenceKey; } final TreeMap.Entry nextEntry() { TreeMap.Entry e = next; if (e == null || e.key == fenceKey) throw new NoSuchElementException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); next = successor(e); lastReturned = e; return e; } final TreeMap.Entry prevEntry() { TreeMap.Entry e = next; if (e == null || e.key == fenceKey) throw new NoSuchElementException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); next = predecessor(e); lastReturned = e; return e; } final void removeAscending() { if (lastReturned == null) throw new IllegalStateException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); // deleted entries are replaced by their successors if (lastReturned.left != null && lastReturned.right != null) next = lastReturned; m.deleteEntry(lastReturned); lastReturned = null; expectedModCount = m.modCount; } final void removeDescending() { if (lastReturned == null) throw new IllegalStateException(); if (m.modCount != expectedModCount) throw new ConcurrentModificationException(); m.deleteEntry(lastReturned); lastReturned = null; expectedModCount = m.modCount; } } final class SubMapEntryIterator extends SubMapIterator > { SubMapEntryIterator(TreeMap.Entry first, TreeMap.Entry fence) { super(first, fence); } public Map.Entry next() { return nextEntry(); } public void remove() { removeAscending(); } } final class DescendingSubMapEntryIterator extends SubMapIterator > { DescendingSubMapEntryIterator(TreeMap.Entry last, TreeMap.Entry fence) { super(last, fence); } public Map.Entry next() { return prevEntry(); } public void remove() { removeDescending(); } } // Implement minimal Spliterator as KeySpliterator backup final class SubMapKeyIterator extends SubMapIterator implements Spliterator { SubMapKeyIterator(TreeMap.Entry first, TreeMap.Entry fence) { super(first, fence); } public K next() { return nextEntry().key; } public void remove() { removeAscending(); } public Spliterator trySplit() { return null; } public void forEachRemaining(Consumer super K> action) { while (hasNext()) action.accept(next()); } public boolean tryAdvance(Consumer super K> action) { if (hasNext()) { action.accept(next()); return true; } return false; } public long estimateSize() { return Long.MAX_VALUE; } public int characteristics() { return Spliterator.DISTINCT | Spliterator.ORDERED | Spliterator.SORTED; } public final Comparator super K> getComparator() { return NavigableSubMap.this.comparator(); } } final class DescendingSubMapKeyIterator extends SubMapIterator implements Spliterator { DescendingSubMapKeyIterator(TreeMap.Entry last, TreeMap.Entry fence) { super(last, fence); } public K next() { return prevEntry().key; } public void remove() { removeDescending(); } public Spliterator trySplit() { return null; } public void forEachRemaining(Consumer super K> action) { while (hasNext()) action.accept(next()); } public boolean tryAdvance(Consumer super K> action) { if (hasNext()) { action.accept(next()); return true; } return false; } public long estimateSize() { return Long.MAX_VALUE; } public int characteristics() { return Spliterator.DISTINCT | Spliterator.ORDERED; } } } /** * @serial include */ static final class AscendingSubMap extends NavigableSubMap { private static final long serialVersionUID = 912986545866124124060L; AscendingSubMap(TreeMap m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); } public Comparator super K> comparator() { return m.comparator(); } public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range"); if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range"); return new AscendingSubMap<>(m, false, fromKey, fromInclusive, false, toKey, toInclusive); } public NavigableMap headMap(K toKey, boolean inclusive) { if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range"); return new AscendingSubMap<>(m, fromStart, lo, loInclusive, false, toKey, inclusive); } public NavigableMap tailMap(K fromKey, boolean inclusive) { if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range"); return new AscendingSubMap<>(m, false, fromKey, inclusive, toEnd, hi, hiInclusive); } public NavigableMap descendingMap() { NavigableMap mv = descendingMapView; return (mv != null) ? mv : (descendingMapView = new DescendingSubMap<>(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive)); } Iterator keyIterator() { return new SubMapKeyIterator(absLowest(), absHighFence()); } Spliterator keySpliterator() { return new SubMapKeyIterator(absLowest(), absHighFence()); } Iterator descendingKeyIterator() { return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); } final class AscendingEntrySetView extends EntrySetView { public Iterator > iterator() { return new SubMapEntryIterator(absLowest(), absHighFence()); } } public Set > entrySet() { EntrySetView es = entrySetView; return (es != null) ? es : (entrySetView = new AscendingEntrySetView()); } TreeMap.Entry subLowest() { return absLowest(); } TreeMap.Entry subHighest() { return absHighest(); } TreeMap.Entry subCeiling(K key) { return absCeiling(key); } TreeMap.Entry subHigher(K key) { return absHigher(key); } TreeMap.Entry subFloor(K key) { return absFloor(key); } TreeMap.Entry subLower(K key) { return absLower(key); } } /** * @serial include */ static final class DescendingSubMap extends NavigableSubMap { private static final long serialVersionUID = 912986545866120460L; DescendingSubMap(TreeMap m, boolean fromStart, K lo, boolean loInclusive, boolean toEnd, K hi, boolean hiInclusive) { super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive); } private final Comparator super K> reverseComparator = Collections.reverseOrder(m.comparator); public Comparator super K> comparator() { return reverseComparator; } public NavigableMap subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { if (!inRange(fromKey, fromInclusive)) throw new IllegalArgumentException("fromKey out of range"); if (!inRange(toKey, toInclusive)) throw new IllegalArgumentException("toKey out of range"); return new DescendingSubMap<>(m, false, toKey, toInclusive, false, fromKey, fromInclusive); } public NavigableMap headMap(K toKey, boolean inclusive) { if (!inRange(toKey, inclusive)) throw new IllegalArgumentException("toKey out of range"); return new DescendingSubMap<>(m, false, toKey, inclusive, toEnd, hi, hiInclusive); } public NavigableMap tailMap(K fromKey, boolean inclusive) { if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range"); return new DescendingSubMap<>(m, fromStart, lo, loInclusive, false, fromKey, inclusive); } public NavigableMap descendingMap() { NavigableMap mv = descendingMapView; return (mv != null) ? mv : (descendingMapView = new AscendingSubMap<>(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive)); } Iterator keyIterator() { return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); } Spliterator keySpliterator() { return new DescendingSubMapKeyIterator(absHighest(), absLowFence()); } Iterator descendingKeyIterator() { return new SubMapKeyIterator(absLowest(), absHighFence()); } final class DescendingEntrySetView extends EntrySetView { public Iterator > iterator() { return new DescendingSubMapEntryIterator(absHighest(), absLowFence()); } } public Set > entrySet() { EntrySetView es = entrySetView; return (es != null) ? es : (entrySetView = new DescendingEntrySetView()); } TreeMap.Entry subLowest() { return absHighest(); } TreeMap.Entry subHighest() { return absLowest(); } TreeMap.Entry subCeiling(K key) { return absFloor(key); } TreeMap.Entry subHigher(K key) { return absLower(key); } TreeMap.Entry subFloor(K key) { return absCeiling(key); } TreeMap.Entry subLower(K key) { return absHigher(key); } } /** * This class exists solely for the sake of serialization * compatibility with previous releases of TreeMap that did not * support NavigableMap. It translates an old-version SubMap into * a new-version AscendingSubMap. This class is never otherwise * used. * * @serial include */ private class SubMap extends AbstractMap implements SortedMap , java.io.Serializable { private static final long serialVersionUID = -6520786458950516097L; private boolean fromStart = false, toEnd = false; private K fromKey, toKey; private Object readResolve() { return new AscendingSubMap<>(TreeMap.this, fromStart, fromKey, true, toEnd, toKey, false); } public Set > entrySet() { throw new InternalError(); } public K lastKey() { throw new InternalError(); } public K firstKey() { throw new InternalError(); } public SortedMap subMap(K fromKey, K toKey) { throw new InternalError(); } public SortedMap headMap(K toKey) { throw new InternalError(); } public SortedMap