Java8之流Stream

java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

流程:

什么是 Stream

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。

特点:

  • 不是数据结构,不会保存数据。
  • 不会修改原来的数据源,它会将操作后的数据保存到另外一个对象中。(保留意见:毕竟peek方法可以修改流中元素)
  • 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算。

流的创建方法

在 Java 8 中, 集合接口有两个方法来生成流:

  • stream() − 为集合创建串行流。
  • parallelStream() − 为集合创建并行流。

常用的创建方法:

1.使用Collection下的 stream() 和 parallelStream() 方法

2.使用Arrays 中的 stream() 方法,将数组转成流

3.使用Stream中的静态方法:of()、iterate()、generate()

4.使用 BufferedReader.lines() 方法,将每行内容转成流

5.使用 Pattern.splitAsStream() 方法,将字符串分隔成流

流的中间操作

1 筛选与切片

  • filter:过滤流中的某些元素
  • limit(n):获取n个元素
  • skip(n):跳过n元素,配合limit(n)可实现分页
  • distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素

  • 映射

  • map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

  • 排序

  • sorted():自然排序,流中元素需实现Comparable接口

  • sorted(Comparator com):定制排序,自定义Comparator排序器

4. 消费

peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。

流的终止操作

1 匹配

聚合操作

  • allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false noneMatch:接收一个
  • Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
  • anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
  • findFirst:返回流中第一个元素
  • findAny:返回流中的任意元素
  • count:返回流中元素的总个数
  • max:返回流中元素最大值
  • min:返回流中元素最小值

2.规约操作

Optional reduce(BinaryOperator accumulator):

第一次执行时,accumulator函数的第一个参数为流中的第一个元素,第二个参数为流中元素的第二个元素;第二次执行时,第一个参数为第一次函数执行的结果,第二个参数为流中的第三个元素;依次类推。

  • T reduce(T identity, BinaryOperator accumulator):
  • 流程跟上面一样,只是第一次执行时,accumulator函数的第一个参数为identity,而第二个参数为流中的第一个元素。
  • U reduce(U identity,BiFunction
  • 在串行流(stream)中,该方法跟第二个方法一样,即第三个参数combiner不会起作用。在并行流(parallelStream)中,我们知道流被fork join出多个线程进行执行,此时每个线程的执行流程就跟第二个方法reduce(identity,accumulator)一样,而第三个参数combiner函数,则是将每个线程的执行结果当成一个新的流,然后使用第一个方法reduce(accumulator)流程进行规约。

3.收集操作

  • collect:接收一个Collector实例,将流中元素收集成另外一个数据结构。
  • Collector
  • supplier():创建一个结果容器A BiConsumer
  • accumulator():消费型接口,第一个参数为容器A,第二个参数为流中元素T。
  • BinaryOperator
  • Function
  • Set

  • CONCURRENT:表示此收集器支持并发。(官方文档还有其他描述,暂时没去探索,故不作过多翻译)

  • UNORDERED:表示该收集操作不会保留流中元素原有的顺序。
  • IDENTITY_FINISH:表示finisher参数只是标识而已,可忽略。

Collector 工具库:Collectors

Collectors.toList() 解析

示例:

输出:

Original: https://www.cnblogs.com/loaderman/p/14216723.html
Author: LoaderMan
Title: Java8之流Stream

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/537809/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • IntelliJ IDEA Maven引入

    posted @2016-04-05 10:13 聊聊IT那些事 阅读(173 ) 评论() 编辑 Original: https://www.cnblogs.com/FCWORL…

    Java 2023年6月6日
    055
  • 线程知识总结3

    一、线程同步 不安全的案例: //不安全买票 public class Demo24_UnsafeBuyTicket { public static void main(Strin…

    Java 2023年6月7日
    076
  • Nginx + FastCgi + Spawn-fcgi + c 的架构

    参考: nginx+c/c++ fastcgi:http://www.yis.me/web/2011/11/01/66.htm cgi探索之路:http://github.tian…

    Java 2023年5月30日
    076
  • redis删除缓存时遇到的问题

    一、redis查询key的方式 redis常用两种方式用于key的精确/模糊匹配 1. KEYS pattern keys pattern用于匹配pattern所有key,会返回当…

    Java 2023年6月13日
    0104
  • java反射与注解

    我们都知道,计算机运行代码,需要经过编译-运行这两个步骤,而反射就是当程序运行状态时,通过类名,就知道这个类有什么属性,有什么方法在里面.简而言之,在 Java 中,只要给定类的名…

    Java 2023年6月8日
    048
  • 解决java以UTF-8输出中文时,excel打开乱码但是记事本打开却正常的问题。

    java 写csv文件,以UTF-8编码输出的时候,文本文件或者notepad++ 打开的时候是正常显示的,但是使用excel打开的时候中文却是乱码。 原因是excel是以ANSI…

    Java 2023年5月29日
    087
  • Mina的IoBuffer改造成Netty的ByteBuff

    背景:部标GPS通讯底层全部改造成基于Netty服务器实现的,现将Mina的依赖移除,修改过程中有用到缓冲区的读写。现做了如下修改: 原有基于Mina的IoBuffer对字节读写封…

    Java 2023年6月9日
    070
  • 创建线程有几种方式?

    创建线程的几种方式 1️⃣ 继承 Thread 类 继承 Thread 类创建线程的步骤为: 1)创建一个类继承Thread类,重写run()方法,将所要完成的任务代码写进run(…

    Java 2023年6月15日
    085
  • 面向对象编程三⼤特性 –封装、继承、多态

    作者:小牛呼噜噜 | https://xiaoniuhululu.com计算机内功、JAVA底层、面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 封装 继承 多态 一道简单的面…

    Java 2023年6月15日
    086
  • spring boot 常见问题

    什么是 Spring Boot? 简单来说,spring boot 底层就是:spring + spring mvc + tomcat + 其他框架 starter; spring…

    Java 2023年6月5日
    083
  • JVM详解

    一、JVM的位置及体系结构 JVM作用在操作系统之上,而Java程序作用在jvm之上,其他的程序则与jvm并列 二、类加载器,及双亲委派机制 1.类加载器 作用:加载Class文件…

    Java 2023年6月13日
    065
  • JDK、JRE、JVM傻傻分不清?

    JDK、JRE、JVM傻傻分不清? 什么是JVM? JVM全称Java Virutal Machine,即Java虚拟机,用来运行Java字节码文件,JVM是Java跨平台运行的关…

    Java 2023年6月5日
    063
  • day02_基本语法

    基本语法 学习目标: 1. 数据类型 2. 变量 3. 编码介绍 4. 标识符和关键字 5. 字符串类型 6. 数据类型转化 7. 进制转换 8. 运算符 一、数据类型 什么是数据…

    Java 2023年6月8日
    059
  • 使用 Certbot 申请 Let’s Encrypt SSL 证书,并定时续期

    网站有个 SSL 证书,可以提高安全性、及提高搜索引擎的排名。Let’s Encrypt SSL 证书是免费的,可以用命令行申请,也可以用命令行续期。 Let&#821…

    Java 2023年6月9日
    067
  • SpringCloud之Seata

    1.Seata是什么? 1.1 概念:Seata 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务。1.2 术语(1)TC: 事务协调者维护全局和分支事务的状态…

    Java 2023年6月13日
    057
  • leetcode 617. Merge Two Binary Trees 合并二叉树(简单)

    一、题目大意 给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新…

    Java 2023年6月14日
    086
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球