Java Stream 流的使用过程解析

 更新时间:2019年10月31日 10:27:14   作者:Mr.O-O  
这篇文章主要介绍了Java Stream 流的使用过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

1. 筛选和切片

用谓词筛选

filter方法接受一个返回boolean的方法。

List<Dish> vegetarianMenu=menu.stream().filter(Dish::isVegetarian) .collect(toList());

distinct去重

distinct方法,根据流中元素的hashCode和equals方法。例:

List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); 
numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);

截短流

limit(n)方法,该方法会返回一个不超过给定长度的流。

如果流是有序的,则最多会返回前n个元素。

limit也可以用在无序流上,比如源是一个Set。这种情况下,limit的结果不会以任何顺序排列。

List<Dish> dishes = menu.stream() .filter(d -> d.getCalories() > 300).limit(3).collect(toList());

跳过元素

skip(n)方法返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一个空流。skip方法和limit方法可以看成是相反的操作。

2. 映射

简单映射

流支持map方法,它会接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素。

下面的代码,对words中的所有字符串应用String::length方法。

List<String> words = Arrays.asList("Java 8", "Lambdas", "In", "Action"); 
List<Integer> wordLengths = words.stream().map(String::length).collect(toList());

流的扁平化

什么叫扁平化?举个例子:把Stream<Stream< String >> 变成 Steam< String > 就叫扁平化。

一言以蔽之,flatmap方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流。

    List<String> words = Arrays.asList("Java 8", "Lambdas", "In", "Action");
    //map函数中每个字符串都被切割为字符串数组,返回一个字符串数组的流
    List<String[]> collect = words.stream()
        .map(word -> word.split(""))
        .distinct()
        .collect(toList());
    //Arrays.stram方法接受一个数组返回一个流
    String[] arrayOfWords = {"Goodbye", "World"};
    Stream<String> streamOfwords = Arrays.stream(arrayOfWords);

    //第一个map返回一个字符串流,流中的元素是一个个的字符串数组。
    //第二个map对每一个字符数组应用Arrays.stream函数,所以每一个字     //符串数组映射为一个字符串流。
    List<Stream<String>> collect1 = words.stream()
        .map(word -> word.split(""))
        .map(v -> Arrays.stream(v))
        .distinct()
        .collect(toList());
    //第一个map返回一个字符串流,流中的元素是一个个的字符串数组。
    //flatMap方法把流中的每个字符串数组都换成一个流,然后连接它们成    //为一个流
    List<String> uniqueCharacters =
        words.stream()
            .map(w -> w.split(""))
            .flatMap(Arrays::stream)
            .distinct()
            .collect(Collectors.toList());

3. 查找和匹配

另一个常见的数据处理套路是看看数据集中的某些元素是否匹配一个给定的属性。Stream API通过allMatch、anyMatch、noneMatch、findFirst、findAny方法提供了这样的工具。

注:这些工具方法的返回值都不是流。所以它们是终端操作

检查谓词是否至少匹配一个元素

if(menu.stream().anyMatch(Dish::isVegetarian)){ 
 System.out.println("The menu is (somewhat) vegetarian friendly!!"); 
}

检查谓词是否匹配所有元素

//是否所有元素都匹配
boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000);
//是否所有元素都 不 匹配
boolean isHealthy = menu.stream().allMatch(d -> d.getCalories() < 1000);

查找元素

findAny方法将返回当前流中的任意元素。

Optional<Dish> dish = menu.stream().filter(Dish::isVegetarian).findAny();

Optional是什么?

查找第一个元素

List<Integer> someNumbers = Arrays.asList(1, 2, 3, 2, 5); 
//filter返回一个流,findfirst在该流中找第一个
Optional<Integer> firstSquareDivisibleByThree = 
 someNumbers.stream() 
 .filter(x -> x == 2) 
 .findFirst(); 

4. 归约

归约:将流中的元素相互结合起来,求一个值。比如学生是元素求分数最高的学生、分数是元素求某位同学的总分。

//求numbers中所有数值的集合
int product = numbers.stream().reduce(1, (a, b) -> a * b);

一个初始值,这里是0;

一个BinaryOperator来将两个元素结合起来产生一个新值,这里我们用的是

lambda (a, b) -> a + b。

无初始值

reduce还有一个重载的变体,它不接受初始值,但是会返回一个Optional对象:

Optional sum = numbers.stream().reduce((a, b) -> (a + b));

小结

该篇对于流的使用,做了简要的笔记。可以满足大多数情况的需求。不要只是看看,不要只是做了笔记。这么好用的api,赶紧用起来吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 解决Android Studio安装后运行出错dose not...和Internal error...

    解决Android Studio安装后运行出错dose not...和Internal error...

    这篇文章主要介绍了解决Android Studio安装后运行出错dose not...和Internal error...的相关资料,需要的朋友可以参考下
    2017-03-03
  • SpringBoot如何自定义线程池配置类

    SpringBoot如何自定义线程池配置类

    有时候我们在项目中做一些长链路的跑批任务时,基于Springboot项目的定时任务,我们可以指定一个自定义的线程配置类进行单独提供给具体跑批任务使用,而不占用整个系统资源,这篇文章主要介绍了SpringBoot如何自定义线程池配置类,需要的朋友可以参考下
    2024-04-04
  • Spring5中的WebClient使用方法详解

    Spring5中的WebClient使用方法详解

    这篇文章主要给大家介绍了关于Spring5中WebClient使用方法的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring5具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-11-11
  • 关于Feign调用服务Headers传参问题

    关于Feign调用服务Headers传参问题

    这篇文章主要介绍了关于Feign调用服务Headers传参问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 一文带你了解Java中的ForkJoin

    一文带你了解Java中的ForkJoin

    这篇文章主要介绍了一文带你了解Java中的ForkJoin,ForkJoinTask本身的依赖关系并不复杂,它与异步任务计算FutureTask一样均实现了Future接口,下文更多相关资料,需要的小伙伴可以参考一下
    2022-04-04
  • 使用spring aop 统一捕获异常和写日志的示例demo

    使用spring aop 统一捕获异常和写日志的示例demo

    本文通过一个小demo给大家介绍spring AOP 实现的异常捕获和日志的方法技巧,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-08-08
  • 在Java中使用日志框架log4j的方法

    在Java中使用日志框架log4j的方法

    Log4j有三个主要的组件/对象:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出,今天通过本文给大家分享Java日志框架log4j的相关知识,感兴趣的朋友一起看看吧
    2021-08-08
  • Java开启新线程并传参方法代码实现

    Java开启新线程并传参方法代码实现

    这篇文章主要介绍了Java开启新线程并传参方法代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • 关于动态参数使用@PathVariable的解析

    关于动态参数使用@PathVariable的解析

    这篇文章主要介绍了关于动态参数使用@PathVariable的解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Java 中的 this 和 super 区别

    Java 中的 this 和 super 区别

    这篇文章主要介绍了Javathis与super本质区别,this与super是类实例化时通往Object类通道的打通者;this和super在程序中由于其经常被隐式的使用而被我们忽略,但是理解其作用和使用规范肯定是必须的。接下来将详述this与super的作用和区别,需要的朋友可以参考一下
    2021-11-11

最新评论