暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java8特性之Stream简介

看点有用的 2021-10-17
417

前言


在最近的开发工作中经常用到Stream流来对list进行处理,相比于循环遍历,通过Stream流来处理list不但可以简化代码,而且能够提高系统性能,同时使得开发效率变得更高。本文就对Stream流进行简单的介绍。


Stream流简介


Stream是Java8新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选、排序、聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由终端操作 (terminaloperation) 得到前面处理的结果,它更专注于对数据源进行各种高效的聚合操作和大批量数据操作。


Stream的UML类图如下图所示:


Stream流的特性


Stream流主要包含以下3个特性:

  1. Stream流不是一种数据结构,它本身并不保存数据,只是在原数据集上定义了一组操作。

  2. 这些定义的操作是惰性的,即每当访问到流中的一个元素,才会在此元素上执行这一系列操作。

  3. 由于Stream流不保存数据,因此每个Stream流只能使用一次。


应用在Stream流上的操作可以分成两种:Intermediate(中间操作)和Terminal(终止操作)。中间操作的返回结果都是Stream,故可以多个中间操作叠加使用;终止操作用于返回我们最终需要的数据,并且会产生一个结果,如果一个Stream 流被消费过了,那它就不能被重用,因此只能有一个终止操作。需要注意的是中间操作不是立即发生的,而是当在中间操作创建的新流上执行完终端操作后,中间操作指定的操作才会发生。

流的中间操作还分无状态操作和有状态操作两种:
  • 在无状态操作中,在处理流中的元素时,会对当前的元素进行单独处理。比如,过滤操作,因为每个元素都是被单独进行处理的,所有它和流中的其它元素无关。

  • 在有状态操作中,某个元素的处理可能依赖于其他元素。比如查找最小值,最大值,和排序,因为他们都依赖于其他的元素。


Stream流常用方法


如第二节中提到,Stream流的操作分为中间操作和终止操作,因此这两种操作也都对应着不同的方法,本节将主要介绍这两种操作的常用方法:


中间操作常用方法


  • filter():将结果为false的元素过滤掉

  • map():转换元素的值,可以用方法引用或者lambda表达式

  • flatMap():若元素是流,将流摊平为正常元素,再进行元素转

  • limit():保留前n个元素

  • skip():跳过前n个元素

  • distinct():剔除重复元素

  • sorted():将元素进行排序

具体示例代码如下:
List<Integer> num = Arrays.asList(2,4,8,1,0,5,7,1,3,6,9,5);


       num.stream().filter(integer -> integer % 2 == 0// 选出偶数
               .distinct() // 去重
               .sorted((a,b) -> b.compareTo(a)) // 排序
.forEach(a -> System.out.println(a + " ")); // 遍历输出


       num.stream().limit(5// 选出前5个元素
.forEach(System.out::println); //遍历输出


       num.stream().skip(2// 跳过前2个元素
.forEach(System.out::println); //遍历输出


       num.stream().map(a -> a + 1// 每个元素+1
               .collect(Collectors.toList())
.forEach(System.out::println); //遍历输出
复制


终止操作常用方法

约简操作

  • max():返回最大值元素

  • min():返回最小值元素

  • count():返回元素数量

  • findFirst():返回第一个元素

  • findAny():返回任意元素

  • anyMatch():任意元素匹配时返回true

  • allMatch():所有元素匹配时返回true

  • noneMatch():没有元素匹配时返回true

  • reduce():合并流中的元素


具体示例代码如下:
List<Integer> num = Arrays.asList(2,4,8,1,0,5,7,1,3,6,9,5);

long count =num.stream().filter(integer -> integer % 2 == 0)


.count(); // 选出偶数个数


System.out.println(num.stream().allMatch(a -> a >5)); //false


System.out.println(num.stream().anyMatch(a -> a >5)); //true


System.out.println(num.stream().noneMatch(a -> a >5)); //false
复制


收集操作
  • forEach():对流中的每个元素进行操作

  • toArray():将流中的所有元素转换成为一个数组

具体示例代码如下:
List<Integer> num = Arrays.asList(2,4,8,1,0,5,7,1,3,6,9,5);
Integer[] nums = num.stream().toArray(Integer[] :: new); //list转换为数组
复制

小结


本文主要介绍了Stream流的特性、常用的方法以及方法的使用,在日后的开发工作中可以尝试多使用Stream流来代替传统的遍历方式,进而提升系统性能以及代码可读性,提高日常的开发效率。

文章转载自看点有用的,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论