Java 的 NavigableSet 接口(即 java.util.NavigableSet)是 SortedSet 接口的子类型。因此,NavigableSet 继承了 SortedSet 的核心行为(如元素排序特性),同时在此基础上新增了一组专门用于元素导航的方法。在本文中,我将深入讲解 Java NavigableSet 中部分常用的导航方法。
在 Java 6 至 Java 13 版本中,java.util 包中仅有 java.util.TreeSet 类实现了 NavigableSet 接口。尽管 java.util.concurrent 包中存在 ConcurrentSkipListSet 这一实现类,但它不在本教程的讨论范围内。
如下图:
要创建 Java 中的 NavigableSet,需实例化一个实现了 NavigableSet 接口的类。以下是创建 TreeSet 实例的示例(TreeSet 类实现了 NavigableSet 接口):
NavigableSet<String> set = new TreeSet<>(); set.add("about"); set.add("sport"); set.add("dance");
descendingSet() 方法会返回一个 NavigableSet,其元素顺序与当前集合的顺序完全相反。需要注意的是,返回的集合是原始 NavigableSet 的 “视图”—— 它并非独立的新集合,而是依赖原始集合存在,因此对这个降序集合所做的修改,也会同步反映到原始集合中。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetExample { public static void main(String[] args) { // 创建一个NavigableSet并添加元素 NavigableSet<Integer> numbers = new TreeSet<>(); numbers.add(10); numbers.add(20); numbers.add(30); numbers.add(40); // 获取降序视图 NavigableSet<Integer> descendingNumbers = numbers.descendingSet(); System.out.println("原始集合(升序): " + numbers); System.out.println("降序视图集合: " + descendingNumbers); // 对降序视图进行修改 descendingNumbers.add(25); System.out.println("\n添加元素25后:"); System.out.println("降序视图集合: " + descendingNumbers); System.out.println("原始集合(自动维持排序): " + numbers); } }
运行结果:
原始集合(升序): [10, 20, 30, 40] 降序视图集合: [40, 30, 20, 10] 添加元素25后: 降序视图集合: [40, 30, 25, 20, 10] 原始集合(自动维持排序): [10, 20, 25, 30, 40]
descendingIterator() 方法允许你以相反顺序迭代 NavigableSet(本身也是 SortedSet)中的元素,且不会改变集合内部的原始排序。例如:
package com.hxstrive.java_collection.set; import java.util.Iterator; import java.util.NavigableSet; import java.util.TreeSet; public class DescendingIteratorExample { public static void main(String[] args) { // 创建NavigableSet并添加元素 NavigableSet<String> fruits = new TreeSet<>(); fruits.add("apple"); fruits.add("banana"); fruits.add("cherry"); fruits.add("date"); System.out.println("原始集合(自然排序): " + fruits); // 使用descendingIterator()逆序迭代 System.out.println("逆序迭代结果:"); Iterator<String> descendingIterator = fruits.descendingIterator(); while (descendingIterator.hasNext()) { System.out.println(descendingIterator.next()); } // 验证原始集合顺序未改变 System.out.println("\n迭代后原始集合: " + fruits); } }
运行结果:
原始集合(自然排序): [apple, banana, cherry, date] 逆序迭代结果: date cherry banana apple 迭代后原始集合: [apple, banana, cherry, date]
headSet() 方法会返回原始 NavigableSet 的一个视图,这个视图中仅包含所有 “小于” 给定元素的元素(判断依据为集合的排序规则)。以下是具体示例:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.SortedSet; import java.util.TreeSet; public class NavigableSetHeadSetExample { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("2"); original.add("3"); original.add("4"); // headset1 包含所有小于 "3" 的元素:"1"、"2" SortedSet<String> headset1 = original.headSet("3"); System.out.println("headSet(\"3\") 结果:" + headset1); // headset2 包含所有小于等于 "3" 的元素:"1"、"2"、"3"(因 inclusive=true) NavigableSet<String> headset2 = original.headSet("3", true); System.out.println("headSet(\"3\", true) 结果:" + headset2); } }
运行结果:
headSet("3") 结果:[1, 2] headSet("3", true) 结果:[1, 2, 3]
tailSet() 方法的工作方式与 headSet() 方法相同,不同之处在于它返回所有大于或等于给定参数元素的元素。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("2"); original.add("3"); // tailSet 将包含 “2” 和 “3” SortedSet<String> tailSet = original.tailSet("2"); System.out.println(tailSet); // [2, 3] // tailSet2 将仅包含 “3”,因为 “inclusive” 参数设为 false NavigableSet<String> tailSet2 = original.tailSet("2", false); System.out.println(tailSet2); // [3] } }
运行结果:
[2, 3] [3]
subSet() 方法允许你传入两个参数,用于划定要返回的视图集合的边界。符合第一个边界的元素会被包含在内,而符合最后一个边界的元素则不会被包含。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("2"); original.add("3"); original.add("4"); original.add("5"); // subset 将包含 "2" 和 "3" SortedSet<String> subset = original.subSet("2", "4"); System.out.println("subset=" + subset); // subset2 将包含 "2", "3" 和 "4" // 因为 fromInclusive=true 和 toInclusive=true NavigableSet<String> subset2 = original.subSet("2", true, "4", true); System.out.println("subset2=" + subset2); } }
运行结果:
subset=[2, 3] subset2=[2, 3, 4]
ceiling() 方法返回此集合中大于或等于传递给 ceiling() 方法的参数元素的最小元素。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("3"); original.add("5"); String ceiling = original.ceiling("2"); System.out.println("ceiling=" + ceiling); // ceiling=3 } }
运行结果:
ceiling=3
floor() 方法与 ceiling() 方法的作用相反,它会返回小于或等于给定参数值的最大元素。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("3"); original.add("5"); String floor = original.floor("2"); System.out.println("floor=" + floor); // ceiling=3 } }
运行结果:
floor=1
higher() 方法会返回此集合中大于(不等于)作为参数传递给 higher() 方法的元素的最小元素。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("2"); original.add("3"); String higher = original.higher("2"); System.out.println("higher=" + higher); } }
运行结果:
higher=3
lower() 方法与 higher() 方法的作用相反,它会返回小于(不等于)给定参数的最大元素。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("2"); original.add("3"); String lower = original.lower("2"); System.out.println("lower=" + lower); } }
运行结果:
lower=1
pollFirst() 方法会返回并移除 NavigableSet 中的“第一个”元素,如果集合为空,则返回 null。“第一个”指的是根据集合的排序规则确定的最小元素。例如:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("2"); original.add("3"); String first = original.pollFirst(); System.out.println("first=" + first); } }
运行结果:
first=1
pollLast()方法会返回并移除NavigableSet中的“最后一个”元素。“最后一个”指的是根据集合的元素排序规则确定的最大元素。以下是一个Java的NavigableSet的pollLast()示例:
package com.hxstrive.java_collection.set; import java.util.NavigableSet; import java.util.TreeSet; public class NavigableSetDemo { public static void main(String[] args) { NavigableSet<String> original = new TreeSet<>(); original.add("1"); original.add("2"); original.add("3"); String last = original.pollLast(); System.out.println("last=" + last); } }
运行结果:
last=3