1. 在集合中查找元素
使用标准方法进行查找
当我们有一个列表,例如名字列表:
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
Java 提供了几个便捷的查找方法:
- contains(Object o) — 检查集合中是否包含该元素。
- indexOf(Object o) — 返回元素第一次出现的索引(如果未找到则为 -1)。
- lastIndexOf(Object o) — 返回元素最后一次出现的索引(或 -1)。
示例:
System.out.println(names.contains("Anna")); // true
System.out.println(names.indexOf("Anna")); // 0
System.out.println(names.lastIndexOf("Anna")); // 3
System.out.println(names.contains("Sergey")); // false
事实: 对于 Set 这类集合,没有 indexOf 和 lastIndexOf 方法 — Set 根本没有索引,只有唯一值。
按条件查找
有时需要找到满足某个条件的元素,而不是某个确定的值。例如,找到第一个长度大于 6 的名字。普通的 for 循环就很合适:一旦找到符合条件的元素——使用 break 跳出即可。
List<String> names = List.of("Anna", "Boris", "Viktoriya", "Anna", "Dmitriy");
String found = null;
for (String name : names) {
if (name.length() > 6) {
found = name;
break; // 找到第一个符合条件的元素后即可退出循环
}
}
System.out.println(found); // Viktoriya
查找最大值与最小值
对于元素可比较的集合(例如数字),可以使用 Collections 快速找到最大值与最小值。
List<Integer> numbers = List.of(10, 5, 20, 7, 20, 3);
int max = Collections.max(numbers); // 20
int min = Collections.min(numbers); // 3
System.out.println("最大值: " + max);
System.out.println("最小值: " + min);
重要: 元素必须是可比较的(实现了 Comparable),否则需要传入比较器。
2. 集合的排序
按默认规则排序列表
只能对可变列表进行排序(例如 ArrayList、LinkedList)。像 Set 和 Map 这类集合不支持直接排序。
默认按“自然顺序”排序:数字按升序,字符串按字母序。
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
Collections.sort(numbers);
System.out.println(numbers); // [1, 3, 5, 7]
也可以通过列表的 sort 方法实现相同效果:
List<Integer> numbers = new ArrayList<>(List.of(5, 1, 7, 3));
numbers.sort(null); // null 表示:使用自然顺序
System.out.println(numbers); // [1, 3, 5, 7]
使用比较器排序
如果需要自定义规则——例如按字符串长度排序:
List<String> words = new ArrayList<>(List.of("cat", "elephant", "mukha", "rhino"));
words.sort(Comparator.comparingInt(String::length));
System.out.println(words); // [cat, elephant, mukha, rhino]
逆序:
words.sort(Comparator.comparingInt(String::length).reversed());
System.out.println(words); // [rhino, mukha, elephant, cat]
旧式写法,使用 Collections.sort:
Collections.sort(words, Comparator.comparingInt(String::length));
3. 不同集合的排序特性
排序只会改变列表
排序方法(sort、Collections.sort)只适用于支持元素顺序的集合(例如 List)。对于 Set 和 Map 并未提供此类方法。
尝试对 Set 排序:
Set<Integer> mySet = new HashSet<>(List.of(3, 1, 2));
Collections.sort(mySet); // 编译错误:sort 需要的是 List!
如果需要从 Set 得到一个已排序的列表:
List<Integer> sortedFromSet = new ArrayList<>(mySet);
Collections.sort(sortedFromSet);
System.out.println(sortedFromSet); // [1, 2, 3]
对 Map 排序:按键和按值
无法直接对 Map 排序,但可以:
- 获取“键-值”对的列表
- 按所需方式对其排序
- 必要时再收集为新的 Map
示例:按值排序
Map<String, Integer> scores = Map.of(
"Anna", 15,
"Boris", 20,
"Vika", 12
);
List<Map.Entry<String, Integer>> entries = new ArrayList<>(scores.entrySet());
entries.sort(Map.Entry.comparingByValue());
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Vika: 12
// Anna: 15
// Boris: 20
按对象字段排序
假设我们有一个用户类:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
以及用户列表:
List<User> users = new ArrayList<>(List.of(
new User("Anna", 22),
new User("Boris", 18),
new User("Vika", 25)
));
按年龄排序:
users.sort(Comparator.comparingInt(u -> u.age));
System.out.println(users); // [Boris (18), Anna (22), Vika (25)]
逆序:
users.sort(Comparator.comparingInt((User u) -> u.age).reversed());
System.out.println(users); // [Vika (25), Anna (22), Boris (18)]
4. 在查找与排序集合时的常见错误
错误 1:对不可变列表进行排序。 通过 List.of(...) 创建的列表不可修改——调用 sort 会抛出 UnsupportedOperationException。
List<Integer> immutable = List.of(3, 1, 2);
immutable.sort(null); // 会抛出异常!
错误 2:直接对 Set 或 Map 排序。 排序方法不适用于 Set 和 Map。如果需要排序,先把数据转换为列表。
错误 3:错误地比较对象。 比较整数时不要直接相减——可能发生溢出。应使用 Integer.compare 或 Comparator.comparingInt,而不是 u1.age - u2.age。
// users.sort((u1, u2) -> u1.age - u2.age); // 能运行,但在溢出情况下很危险!
错误 4:在复杂查找场景下使用 contains。 contains 只检查完全匹配(基于 equals)。如果要按字符串的一部分或对象字段查找——请使用带条件判断的循环,或使用比较器/流。
GO TO FULL VERSION