stream.png

1 什么是Stream流

Stream 是 Java 8 API 中添加的一个新的语法糖,让开发者可以用一种声明书的骚操作来处理数据。
用起来的感觉,像是将你要处理的元素集合看作是水流, 水在管道中流动, 我们可以在管道的各节点上对元素流进行筛选, 排序,聚合等操作。
这些元素集合经过管道的中间操作处理,最后由终止操作得到最后的结果。

2 创建Stream流

  1. // 1.通过数组创建
  2. String[] arr = {"不","高","兴","就","喝","水"};
  3. Stream<String> stream1 = Arrays.stream(arr);
  4. stream1.forEach(System.out::println);
  5. // 2.通过集合创建
  6. List<String> list = Arrays.asList("不","高","兴","就","喝","水");
  7. // 2.1创建一个顺序流(串行执行)
  8. Stream<String> stream2 = list.stream();
  9. stream2.forEach(System.out::println);
  10. //2.2创建并行流(以多线程方式对流进行操作,底层用的线程池)
  11. // 通过parallel方法把顺序流转成并行流
  12. Stream<String> parallelStream1 = list.stream().parallel();
  13. parallelStream1.forEach(System.out::println);
  14. // 通过集合创建一个并行流
  15. Stream<String> parallelStream2 = list.parallelStream();
  16. parallelStream2.forEach(System.out::println);
  17. // 3.通过Stream的静态方法创建
  18. // 3.1 iterate方法:
  19. Stream<Integer> stream3 = Stream.iterate(1, (x) -> x + 1).limit(6);
  20. stream3.forEach(System.out::println);
  21. // 3.2 of方法:
  22. Stream<String> stream4 = Stream.of("不","高","兴","就","喝","水");
  23. stream4.forEach(System.out::println);
  24. // 3.3 generate方法:
  25. Stream<String> stream5 = Stream.generate(() ->"不高兴就喝水!").limit(3);
  26. stream5.forEach(System.out::println);
  27. // 4.通过数字Stream创建
  28. IntStream intStream1 = IntStream.of(1, 2, 3);
  29. intStream1.forEach(System.out::println);
  30. IntStream intStream2 = IntStream.rangeClosed(1,3);
  31. intStream2.forEach(System.out::println);
  32. // 5.通过random创建无限流
  33. IntStream randomStream = new Random().ints(1,3).limit(3);
  34. randomStream.forEach(System.out::println);

3 Stream 的中间操作


该操作会返回一个新的流,目的主要是对流做数据映射或者过滤之类的操作,之后会返回一个新的流,交给下一个操作使用。这类操作都是惰性化的,并没有真正对流进行遍历。一个流可以后面跟随 0 个或者多个中间操作。
image.png

  • 无状态:元素的操作不依赖之前元素,不受之前元素的影响,这些操作没有内部状态,称为无状态操作
  • 有状态:只有拿到所有的元素之后才能继续操作,这些操作都需要利用到之前元素的内部状态,所以称为有状态操作 ```java String str = “bu gao xing jiu he shui”; // 转成list集合 // 输出:bu gao xing jiu he shui Stream.of(str.split(“ “)).collect(Collectors.toList())
    1. .forEach(System.out::println);
    // 拿到长度大于2的单词 // 输出:gao xing jiu shui Stream.of(str.split(“ “)).filter(s -> s.length() > 2)
    1. .forEach(System.out::println);

// flatMap的使用,可以拿到str中的所有的字母 Stream.of(str.split(“ “)).flatMap(s -> s.chars().boxed()) .forEach(i -> System.out.println((char) i.intValue()));

// filter用来过滤符合条件的元素,peek可以输出流操作中的中间值,主要用来调试代码用 Stream.of(str.split(“ “)).filter(e -> e.length() > 3) .peek(e -> System.out.println(“过滤出来的元素: “ + e)) .map(String::toUpperCase) .peek(e -> System.out.println(“映射过后的元素: “ + e)) .collect(Collectors.toList());

  1. <a name="lCvjK"></a>
  2. # 4 Stream的终止操作
  3. <br />该操作才会返回最终的执行结果。当这个操作执行完成后,就无法继续操作了。随着终止操作的执行,才会真正开始流的遍历,生成执行结果,一个流只能有一个终止操作。<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/1214202/1638184584701-c43152bb-8259-48b7-930c-5ebd5873f7a8.png#clientId=u76de960d-2419-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=424&id=u5a3aa3a2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=424&originWidth=808&originalType=binary&ratio=1&rotation=0&showTitle=false&size=85999&status=done&style=none&taskId=ucc3a49f2-e7a0-4319-aad7-79e5516cc24&title=&width=808)
  4. - 非短路操作:必须所有元素都处理完才能得到最终的结果
  5. - 短路操作:一旦得到符合条件的元素就可以中断流得到最终的结果
  6. ```java
  7. String str = "bu gao xing jiu he shui";
  8. // 使用foreach得到乱序结果(因为用了并行流)
  9. // 输出:n go xu sgbuhiaui hiej
  10. str.chars().parallel().forEach(i -> System.out.print((char) i));
  11. // 使用forEachOrdered得到顺序结果
  12. // 输出bu gao xing jiu he shui
  13. str.chars().parallel().forEachOrdered(i -> System.out.print((char) i));
  14. // 收集到list集合中
  15. // 输出:[bu, gao, xing, jiu, he, shui]
  16. List<String> list = Stream.of(str.split(" "))
  17. .collect(Collectors.toList());
  18. System.out.println(list);
  19. // 使用reduce对字符串进行拼接
  20. // 输出bu_gao_xing_jiu_he_shui
  21. Optional<String> stringOptional = Stream.of(str.split(" "))
  22. .reduce((s1, s2) -> s1 + "_" + s2);
  23. System.out.println(stringOptional.get());
  24. // 计算字符串总长度
  25. // 输出:18
  26. Integer length = Stream.of(str.split(" ")).map(s -> s.length())
  27. .reduce(0, (s1, s2) -> s1 + s2);
  28. System.out.println(length);
  29. // 取长度最大的单词
  30. // 输出:xing
  31. Optional<String> max = Stream.of(str.split(" "))
  32. .max((s1, s2) -> s1.length() - s2.length());
  33. System.out.println(max.get());
  34. // 使用findFirst取第一个元素,取到则中断操作
  35. // 输出:bu
  36. Optional<String> findFirst = list.stream().findFirst();
  37. System.out.println(findFirst.get());

5 Stream流操作实战