如何利用Java 21+ Sequenced Collections处理各类集合逆序元素?
JEP 431 引入的Sequenced Collections给所有有确定遍历顺序的集合(比如有序List、LinkedHashSet、TreeMap这类)提供了统一的API,不用再针对不同集合写不同的逆序逻辑。核心是三个新接口:SequencedCollection<E>、SequencedSet<E>、SequencedMap<K,V>,它们都自带reversed()方法,直接生成逆序视图或副本(视集合类型而定)。
1. List 逆序处理
List(比如ArrayList、LinkedList)实现了SequencedCollection接口,调用reversed()会返回一个逆序视图——原集合修改会同步到视图,反之亦然。如果需要和原集合完全独立的不可变副本,可以结合List.copyOf()包装。
import java.util.ArrayList; import java.util.List; public class ListReverseExample { public static void main(String[] args) { List<String> originalList = new ArrayList<>(List.of("A", "B", "C", "D")); // 获取逆序视图(与原集合联动) List<String> reversedView = originalList.reversed(); System.out.println("逆序视图: " + reversedView); // 输出 [D, C, B, A] // 修改原集合,视图同步变化 originalList.add("E"); System.out.println("原集合修改后逆序视图: " + reversedView); // 输出 [E, D, C, B, A] // 获取不可变的逆序副本 List<String> reversedCopy = List.copyOf(originalList.reversed()); originalList.add("F"); System.out.println("原集合修改后逆序副本: " + reversedCopy); // 输出 [E, D, C, B, A](不受原集合影响) } }
2. Set 逆序处理
只有有序Set(比如LinkedHashSet、TreeSet)实现了SequencedSet接口,无序Set(如HashSet)不支持该特性。reversed()返回逆序的SequencedSet视图,原Set的修改会同步到视图。要生成独立副本,用Set.copyOf()即可。
import java.util.LinkedHashSet; import java.util.Set; public class SetReverseExample { public static void main(String[] args) { Set<String> originalSet = new LinkedHashSet<>(Set.of("X", "Y", "Z")); // 获取逆序视图 Set<String> reversedView = originalSet.reversed(); System.out.println("逆序视图: " + reversedView); // 输出 [Z, Y, X] // 修改原Set,视图同步更新 originalSet.add("W"); System.out.println("原Set修改后逆序视图: " + reversedView); // 输出 [W, Z, Y, X] // 获取不可变逆序副本 Set<String> reversedCopy = Set.copyOf(originalSet.reversed()); originalSet.add("V"); System.out.println("原Set修改后逆序副本: " + reversedCopy); // 输出 [W, Z, Y, X] } }
注意:TreeSet的
reversed()效果和descendingSet()一致,但统一的API调用更简洁。
3. Map 逆序处理
有序Map(比如LinkedHashMap、TreeMap)实现了SequencedMap接口,reversed()返回逆序的SequencedMap视图,键值对的顺序完全反转。此外,SequencedMap还提供了firstEntry()、lastEntry()等便捷方法,配合逆序使用更灵活。
import java.util.LinkedHashMap; import java.util.Map; public class MapReverseExample { public static void main(String[] args) { Map<Integer, String> originalMap = new LinkedHashMap<>(); originalMap.put(1, "One"); originalMap.put(2, "Two"); originalMap.put(3, "Three"); // 获取逆序视图 Map<Integer, String> reversedView = originalMap.reversed(); System.out.println("逆序视图: " + reversedView); // 输出 {3=Three, 2=Two, 1=One} // 修改原Map,视图同步变化 originalMap.put(4, "Four"); System.out.println("原Map修改后逆序视图: " + reversedView); // 输出 {4=Four, 3=Three, 2=Two, 1=One} // 获取不可变逆序副本 Map<Integer, String> reversedCopy = Map.copyOf(originalMap.reversed()); originalMap.put(5, "Five"); System.out.println("原Map修改后逆序副本: " + reversedCopy); // 输出 {4=Four, 3=Three, 2=Two, 1=One} // 结合SequencedMap的便捷方法 System.out.println("逆序Map的第一个条目: " + reversedView.firstEntry()); // 输出 4=Four System.out.println("逆序Map的最后一个条目: " + reversedView.lastEntry()); // 输出 1=One } }
核心注意事项
- 视图与副本的区别:
reversed()返回的大多是视图(除了不可变集合),原集合和视图互相影响;如果需要独立的副本,用List.copyOf()、Set.copyOf()、Map.copyOf()包装。 - 无序集合不支持:只有有确定遍历顺序的集合才实现了Sequenced接口,HashSet、HashMap这类无序集合无法调用
reversed(),会直接编译报错。 - 不可变集合的
reversed():比如List.of()创建的不可变List,reversed()返回的也是不可变的逆序列表,因为原集合本身不可变。
内容的提问来源于stack exchange,提问作者Arvind Kumar Avinash

