流的使用
Posted ceilzcx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了流的使用相关的知识,希望对你有一定的参考价值。
简介
流:(可以将它与集合结合一起学习)
1、元素序列——访问特定元素序列的一组有序值;流的目的在于表达计算。(集合主要目的是存储和访问)
2、源——刘辉使用一个提供数据的源,可以是集合、数组等。
3、数据处理操作——存在大量数据处理的函数,如filter、map、reduce等。流可以顺序或并行执行。
特点:
1、流水线——许多流操作返回一个流,可以将多个操作链接,形成一个流水线。能够时一些优化成为可能,如延迟和短路。
2、内部迭代:相比外部迭代(如:for-each),可以透明并行处理,或用更优化的顺序处理。
例:你发现桌上存在三本书,你打算整理它们:
你:这本书放哪?
我:放左边书架上
你:那这本呢?
我:也放左边书架上
你:那剩下这本呢?
我:也放左边书架上
你是不是觉得这种做法相当蠢,其实只需要问一遍这些书放到哪,当我告诉你放到书架上时,这就是内部迭代,我并没有告诉你怎么去放书,你可以一次性拿两本书,类似与并行操作。
你也可以选择先拿近的书,这就是优化你的处理顺序
注意:
1、流只能遍历一次
2、流水线必须触发一个终端操作,中间操作才会执行。
例:假设你想要从一堆苹果中筛选红苹果,并按重量排序:
//parallStream()利用多喝架构并行执行这段代码。可以使用stream()
List<Apple> result = apples.parallelStream().filter(apple -> apple.getColor().equals("red")) .sorted(Comparator.comparing(Apple::getWeight)).collect(Collectors.toList());
filter和sorted操作都返回一个流,执行流水线操作,collect处理流水线。
流和集合:当你在DVD看一部电影时,DVD里的电影就是一个集合,它包含你电影所有的数据结构;而你在互联网上在线看电影时,就是流的概念,你不可能等到电影所有流都传输到你的电脑。你只需要当前你正在观看画面的那几帧就行了。流和集合存在开始计算的差异。
流是按需计算的;流可以是无线的,但用户需求是有限的。
Stream的方法
一)筛选与切片
1、filter:接受一个谓词(返回为boolean的函数)
2、distinc:返回元素各异(可以参考set,根据 hascode 和 equal 方法实现)的流
3、limit(n):截短流,返回不超过n的的流
4、skip(n):跳过元素,返回去掉前n个元素的流
二)映射
1、类似于类型转换,差别是map创建了一个新的流而不是修改
2、map和flatMap的区别:假设我现在要将单词列表[ “hello”,“world”] --> [ "h" , "e" , "l" , "l" , "o" , "w" , "o" , "r" , "l" , "d"];
代码1 为words中的每一个单词返回了一个String[]类型
代码2 Arrays.stream():可以将一个数组产生一个流,这样返回的String[]类型都映射成一个流的内容(注意:不是流,map产生的流无法合并)并合并成一个流。
List<String> words = Arrays.asList("hello", "world");
1、List<String[]> list = words.stream().map(s->s.split("")).collect(toList());
2、List<String> list = words.stream().map(s -> s.split("")).flatMap(Arrays::stream).collect(toList());
三)查找与匹配
工具(函数):allMatch、anyMatch、noneMatch、findFirst、findAny
补充:三个Match可以看作短路求值。短路求值?有些操作不需要整个流就能得到结果,如:and运算符,如果第一个表达式为false,结果就是false,不需要计算后面的表达式。
findFirst和findAny的区别:findFirst在并行操作时存在限制,findAny限制较少。
四)归约
1、reduce:将流中所有元素反复结合,得到一个值。
List<Integer> numbers = Arrays.asList(1, 3, 4, 5, 6, 7, 8);
int sum = numbers.stream().reduce(0, (a, b) -> a + b); //元素求和
int sum = numbers.stream().reduce(0, Integer::sum); //与上面表达式效果一样
int multipy = numbers.stream().reduce(0, (a, b) -> a * b); //元素求积
总结:
操 作 | 类 型 | 返回类型 | 使用的类型/函数式接口 | 函数描述符 |
filter | 中间 | Stream<T> | Predicate<T> | T -> boolean |
distinct | 中间 | Stream<T> | ||
skip | 中间 | Stream<T> | long | |
limit | 中间 | Stream<T> | long | |
map | 中间 | Stream<R> | Function<T,R> | T -> R |
flatMap | 中间 | Stream<R> | Function<T,Stream<R>> | T -> Stream<R> |
sorted | 中间 | Stream<T> | Comparator<T> | (T, T) -> int |
anyMatch | 终端 | boolean | Predicate<T> | T -> boolean |
noneMatch | 终端 | boolean | Predicate<T> | T -> boolean |
allMatch | 终端 | boolean | Predicate<T> | T -> boolean |
findAny | 终端 | Optional<T> | ||
findFirst | 终端 | Optional<T> | ||
forEach | 终端 | void | Consumer<T> | T -> void |
collect | 终端 | R | Collector<T, A, R> | |
reduce | 终端 | Optional<T> | BinaryOperator<T> | (T, T) -> T |
count | 终端 | long |
以上是关于流的使用的主要内容,如果未能解决你的问题,请参考以下文章