迭代与排序
约 989 字大约 3 分钟
布欧-Lewyon
2026-05-15
集合的操作离不开遍历元素和决定元素顺序。本节覆盖 Iterator 机制、Comparable 与 Comparator 两种排序方式、Collections 工具类以及不可变集合。
Iterator 接口
Iterator 是集合遍历的底层机制。增强 for 循环编译后实际上会转换为 Iterator 调用:
List<String> list = List.of("A", "B", "C");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}Iterator 还有一个重要方法 remove(),可在遍历时安全地删除当前元素(增强 for 无法做到):
List<String> words = new ArrayList<>(List.of("a", "b", "c", "b"));
Iterator<String> it = words.iterator();
while (it.hasNext()) {
if (it.next().equals("b")) {
it.remove(); // ✅ 安全删除
}
}
System.out.println(words); // [a, c]增强 for 编译后的字节码等同于此——理解 Iterator 有助于排查 ConcurrentModificationException。
Iterable 接口
如果一个类实现了 Iterable 接口,它就可以用在增强 for 循环中。这是集合框架顶层 Collection 继承 Iterable 的原因:
public interface Iterable<T> {
Iterator<T> iterator();
}Comparable 接口(自然排序)
Comparable 定义对象的自然顺序。实现 compareTo 方法,返回负数(小于)、0(等于)、正数(大于):
public class Person implements Comparable<Person> {
private final String name;
private final int age;
// 构造器、getter 略
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age); // 按年龄升序
}
}List<Person> people = Arrays.asList(new Person("Alice", 30), new Person("Bob", 25));
Collections.sort(people); // 使用 Person 的 compareToInteger.compare(x, y)避免了x - y可能溢出的问题;String已有compareTo。TreeSet/TreeMap依赖Comparable或Comparator,未提供则抛ClassCastException。
Comparator 接口(自定义排序)
当无法修改类的源码,或需要按多种维度排序时,用 Comparator:
// 按姓名升序
Comparator<Person> byName = Comparator.comparing(Person::getName);
// 按年龄降序(链式组合)
Comparator<Person> byAgeDesc = Comparator.comparingInt(Person::getAge).reversed();
// 先按年龄,年龄相同再按姓名
Comparator<Person> byAgeThenName = Comparator
.comparingInt(Person::getAge)
.thenComparing(Person::getName);List<Person> people = getPeople();
people.sort(byName); // List.sort(Java 8+)
Collections.sort(people, byAgeDesc); // 旧版本写法Comparator是函数式接口,可用 Lambda 或方法引用创建:(a, b) -> a.age() - b.age()。Comparator.naturalOrder()/Comparator.reverseOrder()返回基于Comparable的比较器。
Collections 工具类
List<Integer> nums = new ArrayList<>(List.of(3, 1, 4, 1, 5));
Collections.sort(nums); // 排序
Collections.reverse(nums); // 反转
Collections.shuffle(nums); // 打乱
int max = Collections.max(nums); // 最大值
int min = Collections.min(nums); // 最小值
int freq = Collections.frequency(nums, 1); // 出现次数
Collections.fill(nums, 0); // 全部填充为 0Collections.sort在 Java 8+ 后可以直接用List.sort替代。Collections.unmodifiableList(list)返回只读视图,修改原 list 仍会影响视图。
不可变集合(Java 9+)
List.of、Set.of、Map.of 创建不可变集合,元素不能增删改,且不允许 null:
List<String> immutable = List.of("a", "b", "c");
// immutable.add("d"); // UnsupportedOperationException
Set<Integer> nums = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("A", 1, "B", 2);
Map<String, Integer> map2 = Map.ofEntries(
Map.entry("X", 10),
Map.entry("Y", 20)
);- 不可变集合在内存和性能上比可变集合更优,适合作为常量或方法返回值(防止调用方篡改)。
- Java 10 的
List.copyOf、Set.copyOf、Map.copyOf从现有集合创建不可变副本。
小结
Iterator是增强 for 的底层实现,提供remove()安全删除元素;遍历中修改集合结构需用它。Comparable定义自然排序(修改类的源码),Comparator定义自定义排序(不修改类,可组合)。Collections工具类提供排序、反转、打乱、查找等静态方法;Java 8+ 的List.sort更简洁。- 不可变集合(
List.of/Set.of/Map.of)不可增删改且禁止null;copyOf从现有集合创建不可变副本。 - 易错:
Collections.unmodifiableList返回的只读视图仍受原集合影响——原集合可变意味着视图"非真正不可变"。此外,用Comparator时compare(a, b)应返回负数/0/正数,不要只返回-1/0/1,否则排序算法可能出 bug。 - 思考任务:创建一个
Person列表,先按年龄降序排序,年龄相同按姓名字母序升序,用Comparator链式写法实现。
下一节:IO 流
