227. Java 集合 - 排序Set中的元素 —— SortedSet 与 NavigableSet
1. 🔹 Set还能排序?是的!SortedSet了解一下!
除了普通的Set接口,Java还提供了两个强大的扩展接口:
- SortedSet
- NavigableSet
这两个接口都是为了让集合中的元素保持排序状态而设计的!
2. 🚀 什么是SortedSet?
SortedSet接口的特点是:
✅ 集合中的元素始终按照升序排列(从小到大)。
📢 重要提醒:具体如何实现排序,是由具体的集合实现类(比如
TreeSet)来决定的。
2.1 📌 排序需要比较,那元素怎么比较?
为了让元素可以排序,Java提供了两种标准的比较方式:
| 方式 | 描述 |
|---|---|
1. 实现Comparable接口 |
元素自己知道怎么比较自己,定义compareTo()方法 |
2. 提供一个Comparator
|
在创建集合时指定外部比较器 |
🔹 即使元素本身已经实现了Comparable,你仍然可以通过Comparator来指定不同的排序规则,灵活切换排序方式!
2.2 🛠️ 示例:使用TreeSet(实现了SortedSet)
import java.util.*;
public class SortedSetExample {
public static void main(String[] args) {
// 使用元素自带的自然排序(字母顺序)
SortedSet<String> names = new TreeSet<>();
names.add("Charlie");
names.add("Alice");
names.add("Bob");
System.out.println("Sorted names: " + names);
// 使用Comparator自定义逆序排序
SortedSet<String> reversedNames = new TreeSet<>(Comparator.reverseOrder());
reversedNames.addAll(names);
System.out.println("Reversed sorted names: " + reversedNames);
}
}
运行输出:
Sorted names: [Alice, Bob, Charlie]
Reversed sorted names: [Charlie, Bob, Alice]
3. 🎯 排序(Sorting) vs 顺序(Ordering)
这两个概念非常重要,经常会被混淆:
| 排序(Sorting) | 顺序(Ordering) | |
|---|---|---|
| 定义 | 根据比较逻辑,将元素从小到大(或自定义规则)排列 | 保持元素添加进集合的顺序 |
| 例子 | SortedSet | List |
| 特点 | 第一个元素总是最小的 | 第一个元素总是最先添加的 |
| 实现 | TreeSet | ArrayList / LinkedList |
4. 📚 SortedSet支持的新操作
在普通Set基础上,SortedSet增加了以下操作:
✅ 获取最小元素(first())和最大元素(last())
✅ 截取某一范围内的元素:
- headSet(E toElement):取出比指定元素小的所有元素
- tailSet(E fromElement):取出比指定元素大的所有元素 ✅ 迭代时总是从最小元素开始,到最大元素结束
5. 🔥 再升级:NavigableSet!
NavigableSet是SortedSet的子接口,它增加了更多灵活操作,比如:
✅ 可以反向遍历元素(从大到小)
✅ 更方便地获取:
-
刚好小于某元素的元素(
lower()) -
刚好大于某元素的元素(
higher()) -
小于等于(
floor()) -
大于等于(
ceiling())
🛠️ 示例:NavigableSet操作
import java.util.*;
public class NavigableSetExample {
public static void main(String[] args) {
NavigableSet<Integer> numbers = new TreeSet<>(Arrays.asList(10, 20, 30, 40, 50));
System.out.println("Numbers: " + numbers);
System.out.println("Lower than 30: " + numbers.lower(30)); // 20
System.out.println("Higher than 30: " + numbers.higher(30)); // 40
System.out.println("Floor of 30: " + numbers.floor(30)); // 30
System.out.println("Ceiling of 25: " + numbers.ceiling(25)); // 30
// 反向遍历
System.out.println("Descending order: " + numbers.descendingSet());
}
}
运行输出:
Numbers: [10, 20, 30, 40, 50]
Lower than 30: 20
Higher than 30: 40
Floor of 30: 30
Ceiling of 25: 30
Descending order: [50, 40, 30, 20, 10]
📌 小总结
| 特性 | SortedSet | NavigableSet |
|---|---|---|
| 是否升序排列? | 是 | 是 |
| 是否支持范围查询? | 是 | 是 |
| 是否支持反向遍历? | 否 | ✅ 是 |
| 是否能方便地取floor/ceiling等? | 否 | ✅ 是 |
🎤 小建议
-
举例互动
“如果我想要一个集合,不但去重,还要求元素自动按大小排列,我该选哪个?(答案:TreeSet)”
-
小结过渡
“我们了解了Set还能排序,那么下一步,咱们来看看Map接口,它也可以排序!而且,Map中是存储‘键值对’哦!”