栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

# JDK1.8新特性(二):Stream API

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

# JDK1.8新特性(二):Stream API

    • Stream
      • 对Stream的操作
        • 获取Stream操作
        • 中间操作,一系列流水操作
          • 过滤、截断、跳过、筛选
            • 过滤:stream的filter方法
            • 截断:stream的limit方法
            • 跳过:stream的skip方法
            • 筛选:stream的distinct方法
          • 映射
          • 排序
        • 中止操作
          • allMatch
          • anyMatch
          • noneMatch
          • findFirst
          • findAny
          • count
          • max
          • min
          • 归约与收集
            • 归约
            • map-reduce模式
          • 收集
          • 归约与收集的区别

Java8两个最为重要的改变

  • Lambda表达式
  • Stream API
Stream

Stream,翻译成流,流一般用来对数据进行操作,比如IO流,就是对文件的二进制数据进行操作,常用来序列化

流其实就是数据的渠道,用来操作数据源所生成的元素序列的!

  • Stream不会自己存储元素,其就是元素序列而已
  • Stream不会改变原来对象,可以利用流去产生一个持有结果的stream,再产生新对象
  • Stream的操作是延迟执行的,要等到需要结果的时候才会去执行
对Stream的操作

流一般来源于数据源(文件、集合、数组),所以,有数据源才有流,有了数据源,我们就可以获取其流,进行一系列的流水操作,比如过滤、转换等从而形成一个新流!可以利用新流来产生新的数据对象!

  • 利用一个数据源去获取Stream
  • 对Stream进行中间操作,即一系列流水线操作
  • 终止操作,得到需要的结果
获取Stream操作

通过Collection系列集合提供的Stream,可以获取流

  • stream:串行流
  • paralleStream:并行流

通过Arrays中的静态方法stream去获取数组流

  • stream方法

通过Strean类中的静态方法

  • of方法

创建无限流

  • Stream.iterate(seed,operation) :迭代方式,(给一个种子,给一个成长方程,这个流就会按照成长方程一直生长)
  • Stream.generate:生成方式,无限地按规则去生成流
中间操作,一系列流水操作

要注意一点

中间操作是不会立刻执行的,只有做了终止操作,才会去执行中间操作,并且是一次性的,这个过程就称为惰性延迟,即延迟执行!!!并且执行会发送迭代操作(循环),而且为内部迭代(Stream自身内部的API完成的),而外部迭代为我们自己外部写的循环

过滤、截断、跳过、筛选 过滤:stream的filter方法

其需要的参数为一个Predicate接口(四大函数接口之一),就是一个判断接口!从流中可以去除某些元素

截断:stream的limit方法

截断流可以让元素不超过给定数量,本质上就是限制了内部迭代的次数!并且要注意,多个流水操作只会迭代一次,比如使用了filter再进行limit,不会filter迭代一次,然后limit迭代一次!!!只会两个流水操作同时进行迭代,这个过程称为短路,可以进行提高效率的!一旦发现满足条件的数据就直接返回

跳过:stream的skip方法

返回一个扔掉了前n个元素的流,若流中的元素不足n个,则会返回一个空流

筛选:stream的distinct方法

可以使用distinct来进行去重,本质上是通过流所生成元素的hashCode和equals方法进行去除重复元素的,所以使用这个方法要重写hashCode和equals方法

映射

这里要清楚,集合或数组得到的Stream,本质上是Stream,即里面的元素就是一个Stream,而外层的那个容器也是Stream,里面装有元素Stream

映射对应的方法就是stream的map方法

将元素转化成其他形式或者提取形式,本质上是接受一个函数(Function接口,四大函数式接口之一)作为参数,然后这个函数会被作用到流中的每个元素,从而产生一个新元素!(传递的Function接口的返回值就变成一个新元素)

还有另外一个方法是flatMap

map的作用是对流中的每一个元素进行操作,从而产生一个新元素,所以map返回的stream是元素组合为Stream,而flatMap,仍是是对流中的每一个元素进行操作,但产生的所有新元素会被组合成一个新元素,也就是flatMap的stream是一个元素!即返回一个Stream

排序

排序总共有两种

  • 自然排序:Comparable(内部排序,类实现Comparable接口,实现comparaTo方法)
  • 定制排序:Comparator(外部排序,创建Comparator接口实现类,也是一个函数式接口)

对应的方法为sorted

默认无参就是自然排序,给了Lambda表达式实现Comparator就是定制排序

中止操作

前面提到过,获取了Stream进行中间操作时,是不会立刻执行的,只有等中止操作发生了之后,所有的中间操作才会执行

基本的中止操作有下面几种

  • allMatch:检查是否匹配所有元素
  • anyMatch:检查是否至少匹配一个元素
  • noneMatch:检查是否没有匹配所有元素
  • findFirst:返回第一个元素
  • findAny:返回当前流中的任意一个元素
  • count:返回流中元素的总个数
  • max:返回流中的最大值
  • min:返回流中最小值
allMatch

参数需要一个predicate接口(四大函数式接口之一,用于判断)!

该操作用于判断是否所有元素都符合规则

anyMatch

与allMatch使用方式相同,不过该操作用于判断是否有元素符合规则(只要存在一个)

noneMatch

使用方式一致,用于判断是否所有元素都不符合规则!

findFirst

返回处理Stream后的第一个结果,返回一个Optional对象,Optional是一个容器,这也是JDK8的一个新特性,用来避免返回对象为空的,只要有可能为空,就一定会封装在Optional中!并且能用其orElse方法来进行替换空

使用get方法就能取出里面的对象

findAny

返回处理Stream后的随便一个结果,同理也是返回一个Optional对象

count

返回流中元素的总个数

max

返回流中的最大值,并且使用定制排序,即Compartor接口

min

与max同样使用,只不过是获取最小的,同理使用定制排序

下面来看一下特殊的中止操作

归约与收集 归约

归约可以将流中元素反复结合起来,从而可以得到一个值,其实本质上就是一个循环遍历Stream的元素,第一个元素与起始值做了指定运算后,其结果会与下一个元素继续做指定运算,其实跟result += result类似

上面这段代码就是做了一个累加的操作,从0+1+。。。+10

首先第一次起始值0作为x,第一个元素1作为y,第二次就是第一次的结果作为x,第二个元素2作为y

有了归约就可以进行聚合运算了!替代mysql的group函数做聚合操作

可以看到,假如没有给reduce初始值,那就有可能为空,就会返回一个Optional对象,其必须给的参数是一个BinaryOperator函数式接口,也就是二元运算接口

map-reduce模式

使用map进行提取,然后使用reduce进行归约操作,在大数据方面经常使用

收集

其作用是将流转换为其他形式,比如将stream变回容器,其实说白了就是进行汇总嘛,同理汇总操作可以进行求和、取平均

对应的为collect方法,其参数需要一个Collector方法,表明需要按什么方式进行收集操作,Collectors类提供了很多静态方法,可以创建常用的Collector实例,比如List、Array、Set

当然我们也可知指定去集合到自己想要的容器

Collectors提供了toCollection方法,其参数为一个Supplier接口(四大函数式接口之一,供给型),传一个容器的构造方法就行

下面是求总数、平均值、总和、最大值和最小值(也就是聚合可以进行的操作,Collect都能实现)


我们也可以使用收集进行分组

上面是根据status进行group by,并且返回一个Map容器,key为status,而value为Employee,这就是根据staus进行分组,

甚至可以进行多级分组,也就是可以根据多个属性进行分组,完全可以替代groupby语句


可以看到Collectors.groupingBy方法有一个方法,即需要属性用来分组,还能再给一个Collectors,下一个Collectors又可以进行分组,也就是分组了之后再进行分组,其本质上跟多个属性分组是一样的!

下面是按status进行分组,然后再根据年龄分组(key为返回的青年、老年和中年),此时的返回值就会变成Map>,status分组里面继续分组

Collector甚至可以分区!比如根据工资分区,满足条件的为一个区,不满足条件的为另外一个区,返回对象为Map,给的参数为一个predicate函数式接口,判断属于哪个区,true区还是false区


我们用Collector进行转换成值时,一般都是什么最大值、最小值和平均值,所以Collectors给转换值直接提供一个对象,该对象可以获取转换值的所有可能性

归约与收集的区别

归约是将流中的元素按一定规则组合起来,可以累加、累减等操作,而收集是将流转换为另一种表现形式,比如变成容器(可以进行分组、可以变成指定集合),变成一个值(最大值、最小值、总和)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/270917.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号