List.Stream()各方法应用

2023-05-16

目录

List.Stream流

stream()优点:

流(stream)的操作类型分为两种:

list.stream();

filter(T -> boolean)

distinct()

sorted() / sorted((T, T) -> int)

limit(long n)

skip(long n)

map(T -> R)

flatMap(T -> Stream)

anyMatch(T -> boolean)

findAny() 和 findFirst()

reduce((T, T) -> T) 和 reduce(T, (T, T) -> T)

unordered()


List.Stream流

Stream 中文称为 “流”,通过将集合转换为这么一种叫做 “流” 的元素序列,通过声明性方式,能够对集合中的每个元素进行一系列并行或串行的流水线操作。函数式编程带来的好处尤为明显。这种代码更多地表达了业务逻辑的意图,而不是它的实现机制。易读的代码也易于维护、更可靠、更不容易出错。

stream()优点:

无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
Stream 就如同一个迭代器(Iterator),单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了。

流(stream)的操作类型分为两种:


Intermediate:一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。

Terminal:一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。

流(stream)的使用详解:
简单说,对 Stream 的使用就是实现一个 filter-map-reduce 过程,产生一个最终结果,或者导致一个副作用(side effect)在这里插入图片描述

 

列子
首先我们先创建一个 Person 泛型的 List

List<Person> list = new ArrayList<>();
list.add(new Person("jack", 20));
list.add(new Person("mike", 25));
list.add(new Person("tom", 30));


Person 类包含年龄和姓名两个成员变量

private String name;
private int age;
stream() / parallelStream()

最常用到的方法,将集合转换为流
List list = new ArrayList();
// return Stream


list.stream();


而 parallelStream() 是并行流方法,能够让数据集执行并行操作

filter(T -> boolean)

保留 boolean 为 true 的元素
保留年龄为 20 的 person 元素

list = list.stream()
            .filter(person -> person.getAge() == 20)
            .collect(toList());

distinct()

去除重复元素,这个方法是通过类的 equals 方法来判断两个元素是否相等的
如例子中的 Person 类,需要先定义好 equals 方法,不然类似[Person{name=‘jack’, age=20}, Person{name=‘jack’, age=20}] 这样的情况是不会处理的

sorted() / sorted((T, T) -> int)

如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序,如 Stream

反之, 需要调用 sorted((T, T) -> int) 实现 Comparator 接口
根据年龄大小来比较:

list = list.stream()
           .sorted((p1, p2) -> p1.getAge() - p2.getAge())
           .collect(toList());

当然这个可以简化为

list = list.stream()
           .sorted(Comparator.comparingInt(Person::getAge))
           .collect(toList());

limit(long n)

返回前 n 个元素

list = list.stream()
            .limit(2)
            .collect(toList());

打印输出 [Person{name=‘jack’, age=20}, Person{name=‘mike’, age=25}]

skip(long n)

去除前 n 个元素

list = list.stream()
            .skip(2)
            .collect(toList());

打印输出 [Person{name=‘tom’, age=30}]

tips:

用在 limit(n) 前面时,先去除前 m 个元素再返回剩余元素的前 n 个元素
limit(n) 用在 skip(m) 前面时,先返回前 n 个元素再在剩余的 n 个元素中去除 m 个元素

list = list.stream()
            .limit(2)
            .skip(1)
            .collect(toList());

打印输出 [Person{name=‘mike’, age=25}]

map(T -> R)

将流中的每一个元素 T 映射为 R(类似类型转换)

List<String> newlist = list.stream().map(Person::getName).collect(toList());

newlist 里面的元素为 list 中每一个 Person 对象的 name 变量

flatMap(T -> Stream)

将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流

List<String> list = new ArrayList<>();
list.add("aaa bbb ccc");
list.add("ddd eee fff");
list.add("ggg hhh iii");
list = list.stream().map(s -> s.split(" “)).flatMap(Arrays::stream).collect(toList());


上面例子中,我们的目的是把 List 中每个字符串元素以” "分割开,变成一个新的 List。
首先 map 方法分割每个字符串元素,但此时流的类型为 Stream<String[ ]>,因为 split 方法返回的是 String[ ] 类型;所以我们需要使用 flatMap 方法,先使用Arrays::stream将每个 String[ ] 元素变成一个 Stream 流,然后 flatMap 会将每一个流连接成为一个流,最终返回我们需要的 Stream

anyMatch(T -> boolean)

流中是否有一个元素匹配给定的 T -> boolean 条件

是否存在一个 person 对象的 age 等于 20:
boolean b = list.stream().anyMatch(person -> person.getAge() == 20);

allMatch(T -> boolean)
流中是否所有元素都匹配给定的 T -> boolean 条件
noneMatch(T -> boolean)
流中是否没有元素匹配给定的 T -> boolean 条件

findAny() 和 findFirst()

findAny():找到其中一个元素 (使用 stream() 时找到的是第一个元素;使用 parallelStream() 并行时找到的是其中一个元素)
findFirst():找到第一个元素

值得注意的是,这两个方法返回的是一个 Optional 对象,它是一个容器类,能代表一个值存在或不存在


reduce((T, T) -> T) 和 reduce(T, (T, T) -> T)

用于组合流中的元素,如求和,求积,求最大值等
计算年龄总和:

int sum = list.stream().map(Person::getAge).reduce(0, (a, b) -> a + b);

与之相同:

int sum = list.stream().map(Person::getAge).reduce(0, Integer::sum);

其中,reduce 第一个参数 0 代表起始值为 0,lambda (a, b) -> a + b 即将两值相加产生一个新值
同样地:

计算年龄总乘积:

int sum = list.stream().map(Person::getAge).reduce(1, (a, b) -> a * b);

也可以

Optional<Integer> sum = list.stream().map(Person::getAge).reduce(Integer::sum);

即不接受任何起始值,但因为没有初始值,需要考虑结果可能不存在的情况,因此返回的是 Optional 类型

count()

返回流中元素个数,结果为 long 类型
collect()
收集方法,我们很常用的是 collect(toList()),当然还有 collect(toSet()) 等,参数是一个收集器接口,这个后面会另外讲
forEach()
返回结果为 void,很明显我们可以通过它来干什么了,比方说:

打印各个元素:

list.stream().forEach(System.out::println);

再比如说 MyBatis 里面访问数据库的 mapper 方法:

向数据库插入新元素:

list.stream().forEach(PersonMapper::insertPerson);

 

unordered()

还有这个比较不起眼的方法,返回一个等效的无序流,当然如果流本身就是无序的话,那可能就会直接返回其本身

参考原作者:

List.stream() 各方法应用_Bulldozer Coder的博客-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

List.Stream()各方法应用 的相关文章

随机推荐

  • SVN 增加patch打包管理

    系统上线后必然面临系统的维护 xff0c 目前我们对系统维护和新需求开发 xff0c 是以打patch包形式更新程序 xff0c 但对打包的文件不能很好的搜寻出来 xff0c 为解决这个问题 xff0c 我新开发一插件 xff0c 在svn
  • 1.1 海思3518E视频编解码的一些概念

    目录 1 1 1 前言1 1 2 视频编解码的基本概念了解 1 1 1 前言 这是我第一次写博客 xff0c 我写博客的目的是为了记录我的学习笔记 xff0c 同时也是想把我的学习记录分享出来 xff0c 供参考学习 这个学习笔记是关于海思
  • Git 客户端 - 可视化工具 Fork 使用

    Fork 是什么 当我们在多人协同开发项目的过程中 xff0c Git 是必不可少的代码托管工具 xff0c 但是繁琐的操作命令 抽象的文件状态 xff0c 多个不同分支需要花费大量的时间进行分配管理与维护 xff0c 至此 Fork 拥有
  • STM32串口外设是否需要加上拉电阻?

    STM32F103串口TX一般设置为GPIO Mode AF PP xff08 复用推挽输出 xff09 xff1b RX一般设置为RX一般设置为GPIO Mode IN FLOATING 模拟输入 xff1b 如图所示 xff0c STM
  • Windows11升级踩坑过程与镜像下载地址汇总

    第一天开始写博客 xff0c 之前一直想写但是各种原因没有开始 xff0c 今天折腾了一天升级完了windows11 xff0c 想分享一下过程和踩的坑 xff0c 也算是给自己一个开始的契机 xff0c 有些东西重新配置的时候看自己的博客
  • STM32CubeMx使用教程(六)—— OLED屏使用

    前言 在前面一章中 xff0c 学习了 串口通信以及定时器 xff0c 本章节中将介绍I2C通信 xff0c 使用 I2C 通信方式点亮 OLED 模块 由于 OLED 模块支持多种通信方式 xff0c OLED 模块的 I2C 通信过程主
  • Intel RealSense D435i深度相机通过点云获取图片中任意点三维信息(python实现)

    引用基础包 import pyrealsense2 as rs import numpy as np import cv2 import os import time 声明了个类 xff0c 以后也许会添加重置旋转等操作 xff0c 目前只
  • 闭包的实现

    概念 xff1a 闭包是指一个函数嵌套另一个函数另一个函数可以访问当前这个函数的局部变量 xff0c 闭包是将函数内部和函数外部连接起来的桥梁 闭包的作用 xff1a 缓存数据 xff0c 延长作用域 优点 xff1a 缓存数据 xff0c
  • 无人机高清远程直播+4G/5G智能多网路由系统

    无人机高清远程直播 43 4G 5G智能多网路由系统 交通拥堵问题一直是困扰交警的首要难题 它所带来的时间浪费 运营成本上升 交通事故 空气污染 噪声污染等问题使得交通拥堵成为制约城市经济和社会发展的 瓶颈 尤其是交通早高峰时段 xff0c
  • 无人机电网线路巡检有哪些优势?分享高效的图像实时回传解决方案

    随着科技的高速发展 xff0c 相关数据和图像资料表明 xff0c 在观察输电线路设备运行情况时 xff0c 无人机技术可以起到相当关键的作用 xff0c 大大减轻了电力员工的作业负担 通过无人机电力巡检 xff0c 可以清楚判断重要部件是
  • Mac软件推荐:NoMachine轻松带你远程控制桌面

    使用NoMachine for Mac与你的设备建立远程桌面连接后 xff0c 通过网络远程桌面就能快速访问你的设备 xff0c 方便快捷 xff0c 安全可靠 xff0c nomachine mac版的功能强大 xff0c 而且还是免费软
  • lodash源码

    function var undefined var VERSION 61 4 17 21 var LARGE ARRAY SIZE 61 200 var CORE ERROR TEXT 61 Unsupported core js use
  • mac系统如何安装nacos

    一 xff1a 安装步骤 1 先到nacos官网 http nacos io zh cn 2 点击前往Github xff08 进去下拉文档 xff0c 找到 latest stable release 点进去 xff09 3 点击下载zi
  • 使用Idea启动Nacos

    通过Edit Configurations进行配置 点击加号 xff0c 并且选择Shell Script 配置参数 xff1a Script path Mac系统的为bin目录 43 startup sh Windows系统为bin目录
  • BoundValueOps(RedisTemplate常用集合)

    目录 boundValueOps Key Value BoundValueOperations set V value get set V value long timeout TimeUnit unit getAndSet V value
  • macOS安装RabbitMQ

    Homebrew 是 MacOS 的一个流行的软件包管理器 可从 Homebrew 的仓库中安装RabbitMQ 首先 xff0c 确保你已经安装了Homebrew 在终端上 xff0c 运行 brew version 1 安装 用以下方法
  • Virtualbox加载虚拟机镜像

    启动虚拟机 打开这个文件夹 双击蓝色图标 会自动开启virtualbox虚拟机 并加载当前镜像 必须保证当前镜像文件所在全部路径都没有中文 建议启动Virtualbox时使用单击右键 gt 管理员方式运行 配置镜像参数 选中镜像 点击设置
  • Docker基础命令

    目录 Docker命令格式 images命令 search命令 pull命令 rmi命令 run命令 ps命令 stop rm命令 启动redis 关闭防火墙 Docker命令格式 Docker命令的语法结构 docker 子命令 选项 d
  • MySQL数据库的应用

    数据库常见术语 DB Database 数据库DBMS Database Management System xff1a 数据库管理系统SQL Structured Query Language xff1a 结构化的查询语言 数据库的设计
  • List.Stream()各方法应用

    目录 List Stream流 stream 优点 xff1a 流 stream 的操作类型分为两种 xff1a list stream filter T gt boolean distinct sorted sorted T T gt i