java 8 Stream

发布时间:2024年01月22日

目录

1. Stream概述

1.1 基本概念

1.2 Stream特性

2. Stream流的创建

3. Stream API分类

3.1 中间操作(返回一个新的Stream)

3.2 终端操作(返回一个新的数据集或值)

4. Collector收集器

参考


1. Stream概述

1.1 基本概念

  1. Stream是java 8引入的特性,与Lambda表达式配合使用时,为我们操作集合(Collection)提供了极大的便利
  2. Stream把要处理的数据集看作一种流,然后借助Stream API对流中的元素进行操作,对流中元素的操作主要分为两种:中间操作(intermediate operation)和终端操作(terminal operation)。中间操作的返回结果是Stream,一次可以有多个中间操作叠加;而终端操作会返回经过操作后的最终数据,一次只能有一个终端操作
  3. 为了执行一次计算,多个Stream操作组成一个Stream流水线(pipeline),流水线中包含一个数据源、若干个中间操作和一个终端操作
  4. Stream和IntStream、LongStream、DoubleStream都是BaseStream接口的子接口,这四个子接口中的方法都差不多,区别在于IntStream、LongStream、DoubleStream直接存储基本数据类型。Stream可以通过mapToInt()/mapToLong()/mapToDouble()方法转换成另外三个Stream

1.2 Stream特性

  1. Stream不是一种数据结构,它不保存数据,而是根据特定的规则对原数据集进行计算/操作
  2. Stream不改变数据源,通常情况下会通过终端操作产出一个新的数据集或值
  3. Stream是惰性(lazy)的,只有当终端操作被初始化后,对数据源的计算操作才会执行

2. Stream流的创建

  • Collection接口的stream()或parallelStream()方法(在实际项目开发中很常见)
  • 静态的Stream.of()、Stream.empty()方法
  • 静态的Stream.iterate()方法生成无限流,接受一个种子值以及一个迭代函数
  • 静态的Stream.generate()方法生成无限流
  • 静态的Arrays.stream()方法
  • 。。。

3. Stream API分类

把Stream中的常用方法按中间操作和终端操作分成两大类。

3.1 中间操作(返回一个新的Stream)

  • filter()方法:把不符合过滤条件的元素过滤掉,即保留结果为true的元素、排除结果为false的元素
  • map()方法:把一个流中的元素按照特定的映射规则进行映射
  • sorted()/sorted(Comparator)方法:把流中元素按照自然序(适合包装类和String类元素)/给定的比较器排序(适合实体类型元素)
  • peek()方法:查看每个元素在经过Stream流水线中某个步骤时的状态,可以用来调试
  • distinct()方法:去除重复元素
  • limit(n)方法:保留前n个元素
  • skip(n)方法:跳过前n个元素
  • mapToInt()/mapToLong()/mapToDouble()方法:把Stream流转换成相应的基本类型流

3.2 终端操作(返回一个新的数据集或值

  • forEach()方法:遍历流中的元素,利用Lambda表达式操作每一个元素,此方法会按特定规则改变流中的每个元素
  • findFirst()/findAny()方法:查找流中的第一个/任意一个(如果是顺序流,默认返回第一个)元素
  • anyMatch()/allMatch()/noneMatch()方法:判断流中是否有符合条件的元素/流中元素是否都符合条件/流中元素是否都不符合条件,返回true/false
  • min()/max()/count()方法:统计流中元素的最值、个数
  • reduce()方法:归约,即缩减把流中的元素缩减成一个值返回,能实现对流中元素的求和求乘积求最值操作
  • reduce(func)方法:接受一个二元函数作为累积器从前两个元素开始持续应用它累积器的中间结果作为第一个参数,流元素作为第二个参数返回Optional类型元素
  • reduce(a, func)方法:与上一个方法类似,多出来的参数a是累积器的起点返回与a同类型元素
  • collect()方法(在实际项目开发中很常见):对经过Stream流水线计算操作后还留在流中的元素进行搜集操作,常和Collector收集器搭配使用

4. Collector收集器

  • Collectors.toList():把流中元素保存在List列表中
  • Collectors.toSet():把流中元素保存在Set集合中、
  • Collectors.toMap():把流中元素保存在Map哈希表中,进一步可分为以下三类方法:
    • Collectors.toMap/toConcurrentMap(func1, func2):两个func分别用来产生键和值,若产生键冲突,报"duplicate key ..."异常
    • Collectors.toMap/toConcurrentMap(func1, func2, func3):func1、func2还是用来产生键和值,func3用于解决键冲突,例如(key1, key2) -> key2,表示有冲突时保留后者(即最新版本)的kv值
    • Collectors.toMap/toConcurrentMap(func1, func2, func3, func4):返回的Map默认是HashMap/ConcurrentHashMap,func4用于指定返回Map的具体类型,可以用对应的构造器引用表示,如HashMap::new
    • 对于上述几个方法,若值为元素本身,则func2可以写成形如 t -> t 的Lambda表达式形式,也可以写成Function.identity()。关于Function.identity()的具体介绍,可以参考以下文章:https://stackoverflow.com/questions/28032827/java-8-lambdas-function-identity-or-t-t、https://www.jianshu.com/p/cd694d2d8be5
  • Collectors.toCollection(Collection):把流中元素保存在指定的集合中,形参是集合的构造器引用
  • Collectors.groupingBy/groupingByConcurrent(func):func是分类函数,生成Map,键是func函数结果,值是具有相同func函数结果的元素的列表
  • Collectors.groupingBy(func1, func2):func2是下游收集器,可以把默认的List列表转换成其他形式,如toSet()、counting()、summingInt/Long/Double(func)、maxBy(Comparator)、minBy(Comparator)、mapping(func1, func2)(func1是转换函数,func2是下游收集器)等
  • Collectors.partitioningBy(func):键是true/false,当func是断言函数(即返回值是boolean类型)时,此方法比groupingBy(func)更高效
  • Collectors.joining()、Collectors.joining(delimiter)、Collectors.joining(delimiter, prefix, suffix):字符串元素连接

参考

  1. https://blog.csdn.net/mu_wind/article/details/109516995
  2. https://blog.csdn.net/lixiaobuaa/article/details/81099838
文章来源:https://blog.csdn.net/weixin_42108602/article/details/135736725
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。