探究Java8的Stream(一)

Java8新特性中我们聊过Lambda表达式和方法引用,这一篇我们来看一下Java8中另一个特性:Stream。

为什么要用这个新特性?

Stream 是用函数式编程方式在集合类上进行复杂操作的工具,其集成了Java 8中的众多新特性之一的聚合操作,开发者可以更容易地使用Lambda表达式,并且更方便地实现对集合的查找、遍历、过滤以及常见计算等。

在Java8中Stream API作为数据渠道,用于操作数组或者集合等数据源。流本身是不存储数据的,只是移动数据,在移动过程中可能会对数据进行过滤,排序或者其它操作,但是,大多数情况下,流操作本身不会修改数据源,比如,对流排序不会修改数据源的顺序。它只是会创建一个新的流,其中包含排序后的结果。

01

Stream的创建

这里还是重新说明以下Stream:Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

我们需要注意下面几点:

Stream不会去存储对象,也不会改变数据源(产生一个新的流)

Steam是延迟操作(在需要结果的时候才去执行)

一个 Stream 只可以使用一次,不能在多次使用。

要怎么操作Stream呢?

操作Stream首先是要创建Steam,然后进行操作(中间操作,这里是一个操作链,对数据源数据进行处理,但是不影响数据源),最后是终止操作。

如何创建Stream呢?有四种方式

1.Java8中Collection提供了两个获取流的方法:

一个是stram()返回一个顺序流,一个是parallelStream()返回的是并行流。

对于顺序流和并行流,我是这样理解的:顺序流就是按照顺序来执行程序,它的速度肯定会比并行执行程序慢。说并行流可能不太理解,但是多线程你肯定很熟悉,并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流,这样执行速度肯定要高。

2.由数组创建流

通过Arrays中的静态方法 stream() 创建数据源

static Stream stream(T[] array): 返回一个流。

3.由值创建流

使用静态方法 Stream.of(), 通过显示值 创建一个流。它可以接收任意数量的参数

4.由函数创建流,创建无限流

什么叫无限流:本人就是这样理解,无限数据的流,(程序一旦跑起来,就停不下来流,可以将下面的例子执行以下看看效果就会明白)

可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流

迭代:public static Stream iterate(final T seed, final UnaryOperator f)

生成:public static Stream generate(Supplier s)

到这里我们就看完了如何创建流了,我们创建完流之后再来看看,中间操作吧,什么叫中间操作呢,中间操作指的是我们用上面的方法使用数据源返回流之后,我们通过一些操作达到我们想要的效果(比如排序,去重等等)

02

中间操作

我们先看一些流操作的API:

一.筛选与切片

filter(Predicate p)接收 Lambda , 从流中排除某些元素

distinct()筛选,通过流所生成元素的 hashCode() 和 equals() 去 除重复元素

limit(long maxSize)截断流,使其元素不超过给定数量

skip(long n)跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补

二.映射

1.map(Function f)接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素

2.mapToDouble(ToDoubleFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream

3.mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream

4.mapToLong(ToLongFunction f)接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream

5.flatMap(Function f)接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

三.排序

1.sorted()产生一个新流,其中按自然顺序排序

2.sorted(Comparator comp)产生一个新流,其中按比较器顺序排序

这里我来说一下映射;map()方法也一样也会返回一个新流,我们把返回的新流称为映射流,我们提供的映射函数会处理原始流中的每一个元素,而映射流中包含了所有经过我们映射函数处理后产生的新元素。

我们首先看一下筛选与切片的功能效果:

例子(对上面的定义进行验证):

构建一个实体类 (其中method是一个静态方法,用于filter中的方法):

Stream的应用

这里控制台会输出ID等于3的那条数据,在我们输出list的时候,我们发现list的数据并没有收到改变,这也验证来上面说的,不会改变数据源。

说到这里本应该继续往下说映射的,但是考虑到虽然讲解了知识点,还是想运用到实际的项目中,这样才能真正理解它,所以关于映射我决定放到下一节再讲(等不及的小伙伴可以现在网上看看哦,资料很多)。

场景:

1.有一个OA项目中有超时提醒(都是发送给操作者,操作者可能有多个,是会签关系(会签关系说明所有操作都审批后才能进入下一个节点))的功能,在某一个审批节点,有的操作者已经批准,而有的操作者还没有批准,那么这个时候如果不想SQL里面去排除,那么我们就可以通过stream来处理。

这也说明了:Stream类似于使用 SQL 执行的数据库查询,但它是一种高效且易于使用的处理数据的方式

2.某个网站把每个来访者IP,以及所停留的页面的时间都记录到缓存中,且要把所有的记录都存入磁盘中(也就是不能影响缓存数据),在每天凌晨分析用户的常见行为以及持久化数据。那我们就可以以流的形式,去除缓存中存入的用户在一个页面的重复数据,并拿到停留时间最久的数据。

今天呢,就先说这么多,还不熟悉的小伙伴可以去练习一下,这对于熟悉Lambad表达式和方法引用也有好处。

跟小伙伴们分享一下这一周的推送安排,大家可以重点关注自己喜欢的文章:

九月10号周一:探究Java8的Stream(一)

九月11号周二:探究Java8的Stream(二)

九月12号周三:关系型数据库之oracle

九月13号周四:探究Java8的Optional 类

九月14号周五:Effective Java(第三版)——条目十四:考虑实现Comparable接口

那么今天小程序更新的题库是什么呢?

关于一些工作中常用的SQL的汇总。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180910G1OP4T00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券