ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 1. stream特点 `Stream` 流分为**顺序流**和**并行流**,所谓顺序流就是按照顺序对集合中的元素进行处理,而并行流则是使用多线程同时对集合中多个元素进行处理,所以在使用并行流的时候就要注意线程安全的问题了。 1. stream不是一种数据结构,不保存数据,只是在原数据上封装了一组操作 2. 这些操作是惰性的,即每当访问到流中的一个元素,才会在此元素上执行这一系列操作。 3. Stream不保存数据,故每个Stream流只能使用一次。 4. 提供并行化流,不用开发人员自己写多线程 ## 2. stream操作分类 可以分成两种:**Intermediate(中间操作)** 和**Terminal(终止操作)**。 1. 中间操作的返回结果都是Stream,故可以多个中间操作叠加; 2. 终止操作用于返回我们最终需要的数据,只能有一个终止操作。 ## 3. 流的产生方法 1. Collection接口的stream()或parallelStream()方法 2. 静态的Stream.of()、Stream.empty()方法 3. Arrays.stream(array, from, to) 4. 静态的Stream.generate()方法生成无限流,接受一个不包含引元的函数 5. 静态的Stream.iterate()方法生成无限流,接受一个种子值以及一个迭代函数 6. Pattern接口的splitAsStream(input)方法 7. 静态的Files.lines(path)、Files.lines(path, charSet)方法 8. 静态的Stream.concat()方法将两个流连接起来 ## 4. 流的Intermediate方法(中间操作) 集合可以直接调用 1. filter(Predicate) 将结果为false的元素过滤掉 2. map(fun) 转换元素的值,可以用方法引元或者lambda表达式 3. flatMap(fun) 若元素是流,将流摊平为正常元素,再进行元素转换 4. limit(n) 保留前n个元素 5. skip(n) 跳过前n个元素 6. distinct() 剔除重复元素 7. sorted() 将Comparable元素的流排序 8. sorted(Comparator) 将流元素按Comparator排序 9. peek(fun) 流不变,但会把每个元素传入fun执行,可以用作调试 ## 5. 流的Terminal方法(终结操作) ### 5.1 约简统计操作 1. max(Comparator) 2. min(Comparator) 3. count() 4. findFirst() 返回第一个元素 5. findAny() 返回任意元素 6. anyMatch(Predicate) 任意元素匹配时返回true 7. allMatch(Predicate) 所有元素匹配时返回true 8. noneMatch(Predicate) 没有元素匹配时返回true 9. reduce(fun) 从流中计算某个值,接受一个二元函数作为累积器,从前两个元素开始持续应用它,累积器的中间结果作为第一个参数,流元素作为第二个参数 10. reduce(a, fun) a为幺元值,作为累积器的起点 11. reduce(a, fun1, fun2) 与二元变形类似,并发操作中,当累积器的第一个参数与第二个参数都为流元素类型时,可以对各个中间结果也应用累积器进行合并,但是当累积器的第一个参数不是流元素类型而是类型T的时候,各个中间结果也为类型T,需要fun2来将各个中间结果进行合并 ### 5.2 收集操作 1. iterator() 2. forEach(fun) 3. forEachOrdered(fun) 可以应用在并行流上以保持元素顺序 4. toArray() 5. toArray(T[] :: new) 返回正确的元素类型 **6. collect(Collector),Collector是收集器,用于将流数据收集成Java集合对象** 7. collect(fun1, fun2, fun3) fun1转换流元素;fun2为累积器,将fun1的转换结果累积起来;fun3为组合器,将并行处理过程中累积器的各个结果组合起来 ### 5.3 实例 ``` public static void streamImpl(List<Student> students) { List<Student> filterStudent = students.stream() .filter(one -> one.getScore() <  60).collect(Collectors.toList()); System.out.println(filterStudent); } ``` #### flatMap() ![](https://img.kancloud.cn/a0/97/a0973785b5627b9db98e39fa82e7ca2c_819x298.png) `flatMap()`操作能把原始流中的元素进行一对多的转换,并且将新生成的元素全都合并到它返回的流里面。假如现每个班的学生都学了不同的课程,现在需要统计班里所有学生所学的课程列表,该如何实现呢? ##### 清单 12. `flatMap ()` 方法的使用示例 ``` `public static void useFlatMap() {` `List<``Student``> students = initData();` `List<``String``> course = students.stream().flatMap(one -> one.getCourse().stream()).distinct()` `.collect(Collectors.toList());` `System.out.println(course);` `}` ``` # 实例 ## 1. reduce实例 Reduce,顾名思义为减少的意思,就是根据指定的计算模型将Stream中的值计算**得到一个最终结果**。首先来看一下Reduce三种形式: ![](https://img.kancloud.cn/91/bb/91bbf658c7d0af8451bb6246b1135b30_871x259.png) 1. 第一种,无初始值,依次累加 ``` public static void reduceFirstSign() { List<Integer> list = Arrays.asList(1,2,3,4,5,6); ptional<Integer> count = list.stream().reduce((a, b) -> (a + b)); System.out.println(count.get()); // 21 } ``` 2. 第二种,有初始值依次计算 ``` public static void reduceSecondSign() { List<Integer> list = Arrays.asList(1,2,3,4,5,6); Integer count = list.stream().reduce(2, (a, b) -> (a * b)); System.out.println(count); // 1440 } ``` (((((2 x 1) x 2) x 3 )x 4) x 5) x 6 ) 3. 第三种,并行化计算统计 ``` public static void main(String[] args) { List<Integer> list = Arrays.asList(2,2); Integer result = list.stream().parallel().reduce(2, (a, b) -> (a + b), (a, b) -> (a + b)); System.out.println(result); } ``` 上面的代码实际上是先使用累加器把 Stream 流中的两个元素都加 `2` 后,然后再使用合并器将两部分的结果相加。最终得到的结果也就是 `8`。 ## 2. 收集器实例 #### list转map 利用收集器 Collectors.toMap ``` public static void list2Map() { List<Student> students = initData(); Map<String, Double> collect = students.stream() .collect(Collectors.toMap(one -> one.getName(), one -> one.getScore())); System.out.println(collect); } ``` ## 6. 流类型转换 ### 6.1 对象流转基本流 对象流转换为基本类型流:mapToInt()、mapToLong()、mapToDouble() ### 6.2 基本流转对象流 基本类型流转换为对象流: boxed() :类似于包装类 mapToObj(func):用函数构造对象