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();
} // 自动关闭
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐