返回
玩转List集合,Java大师的排序、去重、分组、过滤指南
后端
2023-03-09 08:30:53
Java 集合操作进阶:排序、去重、分组、过滤、合并、截取
排序
在编程中,排序是一种至关重要的操作,它允许我们根据特定规则对元素进行排列。在 Java 中,可以通过多种方法对 List 集合进行排序:
- 自然排序: 使用
Collections.sort(List list)
,对数字按大小排序,对字符串按字典顺序排序。 - 自定义排序: 使用
List.sort(Comparator comparator)
,通过自定义比较器实现特定的排序规则。 - 空元素处理: 使用
List.sort(nullsFirst/nullsLast)
,控制空元素的位置。
去重
去重是指从集合中移除重复元素。Java 提供了两种去重方法:
- Set 转换: 将 List 转换为 Set,然后使用
Set.stream().distinct()
去除重复元素。 - 流操作: 直接使用
List.stream().distinct()
去重,效率更高。
分组
分组将集合中的元素根据特定规则划分到不同的组中。Java 提供了两种分组方法:
- 按键值分组: 使用
Collectors.groupingBy(Function<? super T, ? extends K> classifier)
,按分类器映射的键值分组。 - 按键值收集: 使用
Collectors.groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, ?, ? extends V> downstream)
,按键值分组并对每个组使用指定的收集器收集元素。
过滤
过滤从集合中删除不满足指定条件的元素。Java 提供了两种过滤方法:
- 流过滤: 使用
List.stream().filter(Predicate<? super T> predicate)
,通过谓词条件过滤元素。 - 直接过滤: 使用
List.removeIf(Predicate<? super T> filter)
,直接从集合中移除不满足条件的元素。
合并
合并将多个集合合并成一个新的集合。Java 提供了两种合并方法:
- addAll 方法: 使用
Collections.addAll(List list1, List list2)
将 list2 的元素添加到 list1。 - List 合并: 使用
List.addAll(List list)
将 list 的元素添加到当前集合。
截取
截取从集合中提取指定范围内的元素。Java 提供了两种截取方法:
- 子列表: 使用
List.subList(int fromIndex, int toIndex)
从指定位置开始截取元素。 - 流操作: 使用
List.stream().skip(int n).limit(int m)
截取从第 n 个元素开始的 m 个元素。
代码示例
import java.util.*;
public class ListOperations {
public static void main(String[] args) {
// Sorting
List<Integer> numbers = List.of(3, 1, 4, 2, 5);
Collections.sort(numbers); // Natural sorting
System.out.println(numbers); // [1, 2, 3, 4, 5]
// De-duplication
List<String> names = List.of("John", "Mary", "John", "Bob");
List<String> uniqueNames = names.stream().distinct().toList();
System.out.println(uniqueNames); // [John, Mary, Bob]
// Grouping
List<Employee> employees = List.of(
new Employee("John", "Sales"),
new Employee("Mary", "Marketing"),
new Employee("Bob", "Sales")
);
Map<String, List<Employee>> employeesByDepartment = employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
System.out.println(employeesByDepartment); // {Sales=[John, Bob], Marketing=[Mary]}
// Filtering
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.toList();
System.out.println(evenNumbers); // [2, 4]
// Merging
List<Integer> numbers1 = List.of(1, 2, 3);
List<Integer> numbers2 = List.of(4, 5, 6);
List<Integer> mergedNumbers = new ArrayList<>();
mergedNumbers.addAll(numbers1);
mergedNumbers.addAll(numbers2);
System.out.println(mergedNumbers); // [1, 2, 3, 4, 5, 6]
// Sub-listing
List<Integer> sublist = numbers.subList(1, 3); // From index 1 (inclusive) to index 3 (exclusive)
System.out.println(sublist); // [2, 3]
}
private static class Employee {
private String name;
private String department;
public Employee(String name, String department) {
this.name = name;
this.department = department;
}
public String getName() {
return name;
}
public String getDepartment() {
return department;
}
}
}
常见问题解答
-
什么是自然排序?
自然排序是根据元素本身的性质(例如数字大小、字符串字典顺序)进行排序。 -
如何使用自定义比较器进行排序?
自定义比较器是一个实现了 Comparator 接口的类,可以根据特定的规则比较两个元素。 -
如何使用流操作进行过滤?
流操作通过使用 Predicate 接口来过滤元素,返回一个包含符合条件元素的新流。 -
addAll 和 List.addAll 有什么区别?
addAll
方法将一个集合的元素添加到另一个集合,而List.addAll
方法将另一个集合的元素添加到当前 List 中。 -
subList 和 stream().skip(n).limit(m) 有什么区别?
subList
返回一个包含指定范围元素的新 List,而stream().skip(n).limit(m)
返回一个包含指定范围元素的流。