流的使用

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    

以上是关于流的使用的主要内容,如果未能解决你的问题,请参考以下文章

我们如何读取或使用输出流的内容 [关闭]

Java中Steam流的用法及使用备忘

流的使用

Flutter 流的使用

使用stream流的方式过滤和遍历集合

使用stream流的方式过滤和遍历集合