最近实习生们写的steam流 一言难尽,简直,看到代码你都来气
我慷慨一把,简单总结一下
当然,Java 8 引入的Stream API为集合处理提供了强大的功能,它支持一系列丰富的中间操作和终端操作。
一、中间操作(Intermediate Operations)
中间操作不会直接执行任何处理,而是创建一个新的流,直到遇到一个终端操作才开始处理。
1. Filter(过滤)
用于从流中去除不符合条件的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
2. Map(转换)
应用于每个元素上的函数,生成一个新的流。
List<String> words = Arrays.asList("hello", "world");
words.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
3. FlatMap(扁平化映射)
将流中的每个值替换成另一个流,然后将所有的流连接成一个流。
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d")
);
listOfLists.stream()
.flatMap(List::stream)
.forEach(System.out::println);
4. Sorted(排序)
对流中的元素进行排序。
List<Integer> numbers = Arrays.asList(4, 2, 6, 1, 3, 5);
numbers.stream()
.sorted()
.forEach(System.out::println);
5. Distinct(去重)
去除流中重复的元素。
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);
numbers.stream()
.distinct()
.forEach(System.out::println);
6. Peek(查看)
在每个元素上应用函数并打印或做其他操作,主要用于调试。
List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.stream()
.peek(System.out::println)
.forEachOrdered(n -> {});
二、终端操作(Terminal Operations)
终端操作会触发实际的计算,并产生一个结果或副作用。
1. forEach(遍历)
对流中的每个元素执行操作。
List<String> greetings = Arrays.asList("Hello", "World");
greetings.stream()
.forEach(System.out::println);
2. forEachOrdered(有序遍历)
类似forEach,但保证按照流的 encounter order 处理元素。
List<String> greetings = Arrays.asList("Hello", "World");
greetings.stream()
.forEachOrdered(System.out::println);
3. reduce(规约)
将流中的元素组合起来,生成一个单一的结果。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum);
4. collect(收集)
将流的元素收集到一个集合、Map或其他容器中。
List<String> words = Arrays.asList("hello", "world");
List<String> upperCaseWords = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
5. anyMatch、allMatch、noneMatch(匹配)
判断流中是否有元素满足、全部满足或都不满足指定条件。
boolean anyStartsWithH = words.stream()
.anyMatch(s -> s.startsWith("H"));
System.out.println(anyStartsWithH);
6. findFirst、findAny(查找)
查找第一个或任意一个匹配指定条件的元素。
Optional<String> firstWord = words.stream()
.filter(s -> s.length() > 5)
.findFirst();
7. count(计数)
计算流中元素的数量。
long evenCount = numbers.stream()
.filter(n -> n % 2 == 0)
.count();
8. min、max(最小值、最大值)
找到流中的最小或最大元素。
Optional<Integer> maxNumber = numbers.stream()
.max(Integer::compareTo);
三、更复杂的Stream处理示例
1、分组(Grouping)
假设我们有一个Person类,包含属性age和gender,我们可以按年龄和性别分组统计人数。
class Person {
String name;
int age;
String gender;
// 构造方法、getters、setters省略
}
List<Person> people = Arrays.asList(
new Person("Alice", 30, "F"),
new Person("Bob", 25, "M"),
new Person("Charlie", 30, "M"),
// 更多数据...
);
Map<Integer, Map<String, Long>> groupByAgeAndGender = people.stream()
.collect(Collectors.groupingBy(
Person::getAge,
Collectors.groupingBy(Person::getGender, Collectors.counting())
));
System.out.println(groupByAgeAndGender);
2、分区(Partitioning)
根据条件将流分为两部分。
Map<Boolean, List<Person>> partitionedByAge = people.stream()
.collect(Collectors.partitioningBy(p -> p.getAge() > 30));
System.out.println(partitionedByAge);
3、收集到自定义结构(Collect to custom structure)
假设我们要构造一个自定义报告结构,包含每个年龄的平均工资。
class AgeSalaryReport {
int age;
double averageSalary;
// getters、setters省略
}
List<AgeSalaryReport> salaryReports = people.stream()
.collect(Collectors.groupingBy(Person::getAge))
.entrySet().stream()
.map(entry -> new AgeSalaryReport(
entry.getKey(),
entry.getValue().stream()
.mapToInt(Person::getSalary)
.average()
.orElse(0.0)
))
.collect(Collectors.toList());
System.out.println(salaryReports);
4、连接多个Stream操作
结合排序、过滤、映射等操作处理复杂逻辑。
class Task {
String name;
int priority;
LocalDateTime createTime;
// 构造方法、getters、setters省略
}
List<Task> tasks = Arrays.asList(
// 初始化任务列表...
);
List<Task> highPriorityRecentTasks = tasks.stream()
.filter(task -> task.getPriority() >= 5) // 过滤出高优先级任务
.sorted(Comparator.comparing(Task::getPriority).reversed() // 按优先级降序
.thenComparing(Task::getCreateTime).reversed()) // 再按创建时间降序
.limit(10) // 取前10个
.collect(Collectors.toList());
System.out.println(highPriorityRecentTasks);