厌倦了冗长的Java代码?这些隐藏的Stream技巧让你事半功倍
Java的流就像一个宝箱 — 大多数开发人员只是触及了表面。但其中隐藏的宝石可以使你的代码更干净、更快、更优雅,系好安全带 — 我们开始深入挖掘!
1. Null? 没关系! Stream.ofNullable() 会拯救你
Java 9 的Stream.ofNullable()是你的新朋友。它会悄悄地剔除空值,让你免于NullPointerException。
1
2
3
4
5
|
List<String> names = Arrays.asList("Alice", null, "Bob", "Charlie", null);
List<String> filteredNames = names.stream()
.flatMap(Stream::ofNullable) // 👋 再见了, nulls!
.collect(Collectors.toList());
System.out.println(filteredNames); // [Alice, Bob, Charlie]
|
2. 无限的 stream?没错!快去试试Stream.iterate()
瞬间生成序列 — 就像魔术一样!
需要一个无限长的偶数列表? Stream.iterate()可以满足你的需求。
1
2
3
|
Stream.iterate(2, n -> n + 2)
.limit(5)
.forEach(System.out::println); // 2, 4, 6, 8, 10
|
完美解决模拟、游戏、动态数据生成问题
3. Collectors.collectingAndThen():数据处理的瑞士军刀
计算平均工资并将其四舍五入:
1
2
3
4
5
|
long averageSalary = employees.stream()
.collect(Collectors.collectingAndThen(
Collectors.averagingDouble(Employee::getSalary),
Math::round // 💡 瞬间转换
));
|
就问你,够不够优雅!
4. takeWhile() & dropWhile(): 切割集合的利器
Java 9 的动态双子星允许您根据条件拆分集合:
1
2
3
4
|
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> taken = numbers.stream()
.takeWhile(n -> n < 5) // 得到 [1, 2, 3, 4]
.collect(Collectors.toList());
|
1
2
3
|
List<Integer> dropped = numbers.stream()
.dropWhile(n -> n < 5) // 留下 [5, 6, 7, 8]
.collect(Collectors.toList());
|
分页、批量处理或解析数据块的理想选择!
5. Collectors.teeing(): 一石二鸟
同时运行两个Collectors,然后合并结果,Java 12 的 teeing() 改变了并行处理的游戏规则:
1
2
3
4
5
6
7
|
Map<String, Optional<Integer>> minMax = numbers.stream()
.collect(Collectors.teeing(
Collectors.maxBy(Integer::compare), // Finds max
Collectors.minBy(Integer::compare), // Finds min
(max, min) -> Map.of("Max", max, "Min", min)
));
// Output: {Max=Optional[9], Min=Optional[1]}
|
同时获取最大值和最小值
6.额外技巧
- 使用 Stream.concat() 无损合并流。
- 使用 partitioningBy() 将集合分组
- 通过 IntStream.range() 和 rangeClosed() 生成范围,无需循环。
这些功能不仅仅是“锦上添花”——它们是秘密武器,可以:
- 减少 50% 的样板代码
- 预防bug (说的就是你, NullPointerException)
- 增强代码的可读性