传统痛点:
Java 8 之前,集合操作离不开冗长的 for
循环和匿名类。例如,过滤列表中的偶数:
List list = Arrays.asList(1, 2, 3, 4, 5);
List evens = new ArrayList<>();
for (Integer num : list) {
if (num % 2 == 0) evens.add(num);
}
Stream 救场:
一行代码搞定:
List evens = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
核心优势:
作用:只保留符合条件的元素。
语法:filter(Predicate
示例:筛选长度超过3的字符串
List languages = Arrays.asList("Java", "Python", "C++", "Go");
List filtered = languages.stream()
.filter(s -> s.length() > 3)
.collect(Collectors.toList());
// 结果: ["Java", "Python"]
底层逻辑:遍历流中每个元素,保留 predicate.test(element)
为 true
的元素。
注意:filter
是中间操作,返回新流,需配合终端操作(如 collect
)才能执行。
作用:将元素转换为另一种形式。
语法:map(Function super T, ? extends R> mapper)
示例:将字符串转为大写
List upperCase = languages.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
// 结果: ["JAVA", "PYTHON", "C++", "GO"]
进阶玩法:
flatMap
展开多层结构 List> nested = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d"));
List flat = nested.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
// 结果: ["a", "b", "c", "d"]
作用:将元素合并为一个值(如求和、拼接字符串)。
语法:reduce(T identity, BinaryOperator
示例:计算整数列表的总和
List numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream().reduce(0, Integer::sum);
// 结果: 10
魔法细节:
identity
是初始值(如求和时设为 0
)。accumulator
定义如何合并元素(如 a + b
)。String text = "java stream api is powerful and easy to use";
Map wordCount = Arrays.stream(text.split(" "))
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// 结果: {java=1, stream=1, api=1, ...}
关键点:
split(" ")
分割字符串为流。groupingBy
按单词分组,counting
统计次数。List largeList = IntStream.range(0, 1000000)
.parallel() // 切换并行流
.filter(x -> x % 2 == 0)
.boxed()
.collect(Collectors.toList());
System.out.println(largeList );
效率对比:
class Employee {
String name;
int salary;
int age;
// constructor & getters
}
List sorted = employees.stream()
.sorted(Comparator.comparing(Employee::getSalary)
.thenComparing(Employee::getAge))
.collect(Collectors.toList());
System.out.println(sorted);
技巧:链式 Comparator
实现多条件排序。
流只能使用一次
Stream stream = numbers.stream();
stream.forEach(System.out::println); // 正常
stream.forEach(System.out::println); // 报错!流已关闭
避免修改外部变量
int count = 0;
numbers.stream().forEach(n -> count++); // 错误!并行流下可能出错
并行流未必更快
操作 | 传统方式 | Stream 写法 | 爽点 |
---|---|---|---|
过滤偶数 | for + if |
filter(x -> x%2==0) |
代码量减半 |
字符串转大写 | 循环+toUpperCase |
map(String::toUpperCase) |
一行搞定 |
统计总数 | for 累加 |
reduce(0, Integer::sum) |
函数式编程优雅度拉满 |