Java Stream流操作大全:从入门到实战,面试通关必备指南!
·
Stream流的作用
Stream流是集合的进阶操作,它能大大简化我们操作集合的代码量,提高开发效率,优雅!优雅!还是优雅!
stream流的操作
1.获取流
单列集合获取流
//集合.stream()返回一个流
Stream<String> stream1 = list.stream();
Stream<String> stream2 = set.stream();
双列集合获取流
跟据键获取流
先调用map的keySet()方法把集合的key值单独存放在一个单列集合并返回,然后再按照单列集合获取流的方式调用stream()方法返回流
Set<Integer> map1 = map.keySet();
Stream<Integer> stream3 = map1.stream();
跟据值获取流
先调用map的values()方法把集合的valu值单独存放在一个单列集合并返回,然后再按照单列集合获取流的方式调用stream()方法返回流
Collection<String> map2 = map.values();
Stream<String> stream4 = map2.stream();
跟据键值对对象获取流
首先调用entrySet方法把每对键值对一次封装到对象Map.Entry里,然后再把对象依次存入Set集合里
Set<Map.Entry<Integer, String>> map3 = map.entrySet();
Stream<Map.Entry<Integer, String>> stream5 = map3.stream();
数组获取流
String[] arr = {"张颜宇","张三","李四","赵五","刘六","王七"};
Stream<String> stream6 = Stream.of(arr);
2.流的链式调用
流的常用方法
终结方法
forEach(逐一处理)
List<String> list = new ArrayList<>();
list.add("张老三");
list.add("张小三");
list.add("李四");
list.add("赵五");
list.add("张六");
list.add("王八");
// 函数模型:获取流 --> 注意消费流中的元素
list.stream().forEach((String name)->{
System.out.println(name);
});
count(统计个数)
List<String> list = new ArrayList<>();
list.add("张老三");
list.add("张小三");
list.add("李四");
list.add("赵五");
list.add("张六");
list.add("王八");
long count = list.stream().count();
System.out.println("集合中的元素个数是:" + count);
输出结果:
集合中的元素个数是:6
函数拼接
filter(过滤)
// 获取stream流
Stream<String> stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
// 需求:过去出姓张的元素
stream.filter((String name)->{
return name.startsWith("张");
}).forEach((String name)->{
System.out.println("流中的元素" + name);
});
map(映射)
// 获取Stream流
Stream<String> stream1 = Stream.of("11","22","33","44","55");
// 需求:把stream1流中的元素转换为int类型
stream1.map((String s)->{
return Integer.parseInt(s); // 将String类型的s进行转换为Integer类型的元素,并返回
}).forEach((Integer i)->{
System.out.println(i); // 将转换后的int类型的元素逐一输出
});
limit(取用前几个)
// 获取流的长度
Stream<String> stream1 = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
// 需求:保留前三个元素
stream1.limit(3).forEach((String name)->{
System.out.println("流中的前三个元素是:" + name);
});
skip(跳过前几个)
// 获取stream流
Stream<String> stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
stream.skip(3).forEach((String name)->{
System.out.println("跳过前三个,打印剩下的" + name);
});
concat(组合)
Stream<String> stream1 = Stream.of("11","22","33","44","55");
Stream<String> stream2 = Stream.of("张颜宇", "张三", "李四", "赵五", "刘六", "王七");
// 需求:合并两个流
Stream<String> stream = Stream.concat(stream1,stream2);
stream.forEach((String name)->{
System.out.print(name);
});
面试题
1.Q: Stream 与集合的区别是什么?
- •数据存储:集合存储数据,Stream 不存储数据(只传输数据)
- •数据处理:集合支持增删改,Stream 只读(不修改源数据)
- •遍历机制:集合外部迭代(如for-each),Stream 内部迭代(自动并行)
- •数据处理模式:Stream 支持函数式操作(filter/map/reduce)和延迟执行
2.Q: 中间操作 vs 终端操作?
| 类型 | 特点 | 示例 |
|---|---|---|
| 中间操作 | 延迟执行、可链式调用 | filter(), map(), sorted(), distinct() |
| 终端操作 | 触发执行、关闭流 | forEach(), collect(), reduce(), count() |
3.Q: 如何用 reduce() 实现聚合?
// 求和
int sum = Stream.of(1, 2, 3)
.reduce(0, (a, b) -> a + b); // 6
// 找最大值
Optional<Integer> max = Stream.of(1, 5, 3)
.reduce(Integer::max); // Optional[5]
4.Q: 如何避免 NullPointerException?
List<String> names = list.stream()
.filter(Objects::nonNull) // 过滤 null
.map(obj -> obj.getName()) // 可能返回 null 的方法
.filter(Objects::nonNull) // 再次过滤
.collect(Collectors.toList());
5.Q: 何时需要关闭流?
- •只有 I/O 相关的流需要关闭(如
Files.lines()) - •用 try-with-resources 确保关闭:
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
lines.filter(...).count();
} // 自动关闭更多推荐
所有评论(0)