1 什么是Stream流
Stream 是 Java 8 API 中添加的一个新的语法糖,让开发者可以用一种声明书的骚操作来处理数据。
用起来的感觉,像是将你要处理的元素集合看作是水流, 水在管道中流动, 我们可以在管道的各节点上对元素流进行筛选, 排序,聚合等操作。
这些元素集合经过管道的中间操作处理,最后由终止操作得到最后的结果。
2 创建Stream流
// 1.通过数组创建
String[] arr = {"不","高","兴","就","喝","水"};
Stream<String> stream1 = Arrays.stream(arr);
stream1.forEach(System.out::println);
// 2.通过集合创建
List<String> list = Arrays.asList("不","高","兴","就","喝","水");
// 2.1创建一个顺序流(串行执行)
Stream<String> stream2 = list.stream();
stream2.forEach(System.out::println);
//2.2创建并行流(以多线程方式对流进行操作,底层用的线程池)
// 通过parallel方法把顺序流转成并行流
Stream<String> parallelStream1 = list.stream().parallel();
parallelStream1.forEach(System.out::println);
// 通过集合创建一个并行流
Stream<String> parallelStream2 = list.parallelStream();
parallelStream2.forEach(System.out::println);
// 3.通过Stream的静态方法创建
// 3.1 iterate方法:
Stream<Integer> stream3 = Stream.iterate(1, (x) -> x + 1).limit(6);
stream3.forEach(System.out::println);
// 3.2 of方法:
Stream<String> stream4 = Stream.of("不","高","兴","就","喝","水");
stream4.forEach(System.out::println);
// 3.3 generate方法:
Stream<String> stream5 = Stream.generate(() ->"不高兴就喝水!").limit(3);
stream5.forEach(System.out::println);
// 4.通过数字Stream创建
IntStream intStream1 = IntStream.of(1, 2, 3);
intStream1.forEach(System.out::println);
IntStream intStream2 = IntStream.rangeClosed(1,3);
intStream2.forEach(System.out::println);
// 5.通过random创建无限流
IntStream randomStream = new Random().ints(1,3).limit(3);
randomStream.forEach(System.out::println);
3 Stream 的中间操作
该操作会返回一个新的流,目的主要是对流做数据映射或者过滤之类的操作,之后会返回一个新的流,交给下一个操作使用。这类操作都是惰性化的,并没有真正对流进行遍历。一个流可以后面跟随 0 个或者多个中间操作。
- 无状态:元素的操作不依赖之前元素,不受之前元素的影响,这些操作没有内部状态,称为无状态操作
- 有状态:只有拿到所有的元素之后才能继续操作,这些操作都需要利用到之前元素的内部状态,所以称为有状态操作
```java
String str = “bu gao xing jiu he shui”;
// 转成list集合
// 输出:bu gao xing jiu he shui
Stream.of(str.split(“ “)).collect(Collectors.toList())
// 拿到长度大于2的单词 // 输出:gao xing jiu shui Stream.of(str.split(“ “)).filter(s -> s.length() > 2).forEach(System.out::println);
.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());
<a name="lCvjK"></a>
# 4 Stream的终止操作
<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)
- 非短路操作:必须所有元素都处理完才能得到最终的结果
- 短路操作:一旦得到符合条件的元素就可以中断流得到最终的结果
```java
String str = "bu gao xing jiu he shui";
// 使用foreach得到乱序结果(因为用了并行流)
// 输出:n go xu sgbuhiaui hiej
str.chars().parallel().forEach(i -> System.out.print((char) i));
// 使用forEachOrdered得到顺序结果
// 输出bu gao xing jiu he shui
str.chars().parallel().forEachOrdered(i -> System.out.print((char) i));
// 收集到list集合中
// 输出:[bu, gao, xing, jiu, he, shui]
List<String> list = Stream.of(str.split(" "))
.collect(Collectors.toList());
System.out.println(list);
// 使用reduce对字符串进行拼接
// 输出bu_gao_xing_jiu_he_shui
Optional<String> stringOptional = Stream.of(str.split(" "))
.reduce((s1, s2) -> s1 + "_" + s2);
System.out.println(stringOptional.get());
// 计算字符串总长度
// 输出:18
Integer length = Stream.of(str.split(" ")).map(s -> s.length())
.reduce(0, (s1, s2) -> s1 + s2);
System.out.println(length);
// 取长度最大的单词
// 输出:xing
Optional<String> max = Stream.of(str.split(" "))
.max((s1, s2) -> s1.length() - s2.length());
System.out.println(max.get());
// 使用findFirst取第一个元素,取到则中断操作
// 输出:bu
Optional<String> findFirst = list.stream().findFirst();
System.out.println(findFirst.get());