Java 的NavigableMap接口(全限定名:java.util.NavigableMap)是SortedMap接口的子接口。它在SortedMap的基础上扩展了一系列实用方法,能够更便捷地对映射中存储的键和值进行 “导航” 操作(例如精准查找、范围定位等)。
作为一个接口,NavigableMap 本身无法直接实例化,在使用 NavigableMap 前,你需要借助它的具体实现类。在 java.util 包中,NavigableMap 接口仅有一个核心实现类 —— java.util.TreeMap。此外,java.util.concurrent 包中也存在 NavigableMap 的实现类,但该内容不在本教程的讨论范围内。
要创建一个 NavigableMap,你必须创建实现了 NavigableMap 接口的某个类的实例。例如:
NavigableMap<String,String> navigableMap = new TreeMap<>();
除了默认构造方法,你还可以向 TreeMap 构造函数传递一个 Comparator 实现。然后,这个 Comparator 将用于对存储在 NavigableMap 中的键值对的键进行排序。例如:
Comparator<String> comparator = new MyComparatorImpl<String>(); SortedMap<String,String> sortedMap = new TreeMap<>(comparator);
NavigableMap 中第一个实用的导航方法是 descendingKeySet()。该方法会返回一个 NavigableSet,其中元素的排列顺序与原始键集恰好相反。值得注意的是,返回的这个 “视图” 由原始 NavigableMap 的键集提供底层支持,因此对降序键集所做的修改会自动同步到原始集合中。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} System.out.println(map.descendingKeySet()); //[a, b, c, d]
第二种实用的导航方法是 descendingMap()。该方法会返回一个 NavigableMap 对象,作为原始映射的反向视图 —— 视图中元素的排列顺序与原始映射完全相反。由于这是原始映射的视图,因此对该视图所做的任何修改都会自动同步到原始映射中。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} NavigableMap<String,String> reversMap = map.descendingMap(); System.out.println(reversMap); //{a=1000, b=2000, c=3000, d=4000}
headMap() 方法会返回原始 NavigableMap 的一个视图,该视图仅包含“小于”给定元素的元素。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} SortedMap<String,String> headmap1 = map.headMap("b"); System.out.println(headmap1); //{d=4000, c=3000} // inclusive=true NavigableMap<String,String> headmap2 = map.headMap("b", true); System.out.println(headmap2); //{d=4000, c=3000, b=2000}
tailMap() 方法与 headMap() 方法类似,不同之处在于 tailMap() 会返回所有等于或高于给定参数元素的元素。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} SortedMap<String,String> tailMap = map.tailMap("b"); System.out.println(tailMap); //{b=2000, a=1000}
tailMap 变量将引用一个 SortedMap,其中包含来自 NavigableMap 中键为 "b" 和 "a" 的所有键值对,因为这些键被视为等于或大于传递给 tailMap() 方法的参数值 "b"。
subMap() 允许你传递两个参数来划定要返回的视图映射的边界。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} // 获取位于 [c, b) 的条目 SortedMap<String,String> submap1 = map.subMap("c", "b"); System.out.println(submap1); //{c=3000} // fromInclusive=true 且 toInclusive=true,因此 // 获取位于 [c, d] 的条目 NavigableMap<String,String> submap2 = map.subMap("c", true, "b", true); System.out.println(submap2); //{c=3000, b=2000}
ceilingKey() 方法返回此映射中大于或等于传递给 ceilingKey() 方法的参数元素的最小键。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} String ceilingKey = map.ceilingKey("c"); System.out.println(ceilingKey); //c
floorKey() 方法与 ceilingKey() 方法的作用相反。因此,floorKey() 会返回小于或等于传递给 ceilingKey()的参数值的最大键。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} String floorKey = map.floorKey("c"); System.out.println(floorKey); //c
higherKey() 方法会返回此映射中大于(不等于)传递给 higherKey() 方法的参数的最小元素。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} String higherKey = map.higherKey("c"); System.out.println(higherKey); //b
lowerKey() 方法与 higherKey() 方法的作用相反。因此,lowerKey() 会返回小于传递给 lowerKey() 方法的参数值的最大键。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} String lowerKey = map.lowerKey("c"); System.out.println(lowerKey); //d
ceilingEntry() 方法返回 NavigableMap 中不小于(大于或等于)传递给 ceilingEntry() 方法的参数值的最小键所存储的键+值。因此,ceilingEntry() 与 ceilingKey() 方法类似,不同之处在于 ceilingKey() 方法只返回键,而 ceilingEntry() 返回一个包含键和值的 Map.Entry 对象。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} Map.Entry<String,String> ceilingEntry = map.ceilingEntry("c"); System.out.println(ceilingEntry); //c=3000
floorEntry() 方法的作用与 ceilingEntry() 方法相反。floorEntry() 方法会返回键值对,其中的键是小于或等于传递给 floorEntry() 方法的参数值的最大键。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} Map.Entry<String,String> floorEntry = map.floorEntry("c"); System.out.println(floorEntry); //c=3000
higherEntry() 方法返回为大于传递给 higherEntry() 方法的参数值的最小键所存储的键+值。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} Map.Entry<String,String> higherEntry = map.higherEntry("c"); System.out.println(higherEntry); //b=2000
lowerEntry() 方法会返回一个键值对,其中包含的键是所有小于传递给该方法参数值的键中最大的那个。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} Map.Entry<String,String> lowerEntry = map.lowerEntry("c"); System.out.println(lowerEntry); //d=4000
pollFirstEntry() 方法会返回并移除 NavigableMap 中的“第一个”条目(键+值),如果映射为空,则返回 null。“第一个”指的是根据键的排序顺序确定的最小元素。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} Map.Entry<String,String> pollFirstEntry = map.pollFirstEntry(); System.out.println(pollFirstEntry); //d=4000
pollLastEntry() 方法会返回并移除映射中的“最后一个”元素,如果映射为空,则返回 null。“最后一个”指的是根据映射的元素排序顺序确定的最大键。例如:
NavigableMap<String,String> map = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); map.put("a", "1000"); map.put("b", "2000"); map.put("c", "3000"); map.put("d", "4000"); System.out.println(map); //{d=4000, c=3000, b=2000, a=1000} Map.Entry<String,String> pollLastEntry = map.pollLastEntry(); System.out.println(pollLastEntry); //a=1000
更多信息参考 https://docs.oracle.com/javase/8/docs/api/java/util/NavigableMap.html API 文档。