java8学习笔记-Stream流

JDK1.8新增了Stream类,从而把函数式编程的风格引入到Java语言中,Stream类的API提供了强大的功能,使用Stream后,可以写出更加强大,更加简洁的代码

首先,Stream流有一些特性:

  1. Stream流不是一种数据结构,不保存数据,它只是在原数据集上定义了一组操作。
  2. 这些操作是惰性的,即每当访问到流中的一个元素,才会在此元素上执行这一系列操作。
  3. Stream不保存数据,故每个Stream流只能使用一次。

关于应用在Stream流上的操作,可以分成两种:Intermediate(中间操作)和Terminal(终止操作)。中间操作的返回结果都是Stream,故可以多个中间操作叠加;终止操作用于返回我们最终需要的数据,只能有一个终止操作。至于哪些方法是中间操作,哪些方法是终止操作,我们一会儿再说。

使用Stream流,可以清楚地知道我们要对一个数据集做何种操作,可读性强。而且可以很轻松地获取并行化Stream流,不用自己编写多线程代码,可以让我们更加专注于业务逻辑。

默认情况下,从有序集合、生成器、迭代器产生的流或者通过调用Stream.sorted产生的流都是有序流,有序流在并行处理时会在处理完成之后恢复原顺序。unordered()方法可以解除有序流的顺序限制,更好地发挥并行处理的性能优势,例如distinct将保存任意一个唯一元素而不是第一个,limit将保留任意n个元素而不是前n个。

流的常用生成方法

Collection接口的stream()或parallelStream()方法

parallelStream()是并行方法,parallelStream()不一定比stream()快(需要开启线程,线程竞争),而且parallelStream()是线程不安全的,所以使用parallelStream()要综合考量,测试百万数据的List<String> 的System.out.println(),stream()依旧比parallelStream()要快

        List<Integer> list = new ArrayList();Random random = new Random();for (int i = 0; i < 100000; i++) {list.add(random.nextInt());}Instant start = Instant.now();
//        list.stream().forEach(System.out::print); //193毫秒list.parallelStream().forEach(System.out::print);//275毫秒Instant end = Instant.now();System.out.println("");System.out.println("_______________________________________________________________________");System.out.println("end:" + end.toEpochMilli());System.out.println("start:" + start.toEpochMilli());System.out.println("time:" + (end.toEpochMilli() - start.toEpochMilli()));

静态的Stream.of()、Stream.empty()方法

        List<Integer> list = new ArrayList();Random random = new Random();for (int i = 0; i < 100000; i++) {list.add(random.nextInt());}Instant start = Instant.now();
//        Stream.of(list).forEach(System.out::println); //71毫秒Stream.empty().forEach(System.out::println);//37毫秒
//        list.stream().forEach(System.out::print); //193毫秒
//        list.parallelStream().forEach(System.out::print);//275毫秒Instant end = Instant.now();System.out.println("");System.out.println("_______________________________________________________________________");System.out.println("end:" + end.toEpochMilli());System.out.println("start:" + start.toEpochMilli());System.out.println("time:" + (end.toEpochMilli() - start.toEpochMilli()));

Arrays.stream(array, from, to)

包前不包后

        int[] arr = {1, 3, 2, 4, 55, 64, 98, 23};Arrays.stream(arr, 1, 3).forEach(System.out::println); 

流的常用Intermediate方法(中间操作)

filter(Predicate) 将结果为false的元素过滤掉

        int[] arr = {1, 3, 2, 4, 55, 64, 98, 23};//过滤单数保留双数Arrays.stream(arr).filter(item->(item & 1) == 0).forEach(System.out::println);

map(fun) 转换元素的值,可以用方法引元或者lambda表达式

        int[] arr = {1, 3, 2, 4, 55, 64, 98, 23};//filter过滤单数保留双数//map将剩余元素除以2Arrays.stream(arr).filter(item->(item & 1) == 0).map(item -> item / 2).forEach(System.out::println);

flatMap(fun) 若元素是流,将流摊平为正常元素,再进行元素转换

简单点描述就是嵌套的集合扁平化

比如集合里面包含集合/数组 

        List<List<String>> list = Arrays.asList(Arrays.asList("A", "B"),Arrays.asList("C", "D"),Arrays.asList("E", "E"));// 使用 flatMap 扁平化列表List<String> collect = list.stream().flatMap(List::stream).collect(Collectors.toList());System.out.println(collect); //[A, B, C, D, E, E]

或者集合里面本身没有集合/数组但是可以操作(字符串切割)变成集合/数组

        List<Person> list = Arrays.asList(new Person("张三", "1,2,3"),new Person("李四", "2,3"),new Person("王五", "2,4"));Set<Object> collect = list.stream().flatMap(person -> Arrays.stream(person.getHobbies().split(","))).collect(Collectors.toSet());System.out.println(collect);

limit(n) 保留前n个元素 常配合排序使用

        int[] arr = {1, 3, 2, 4, 55, 64, 98, 23};Arrays.stream(arr).limit(2).forEach(System.out::print); //13

skip(n) 跳过前n个元素

        int[] arr = {1, 3, 2, 4, 55, 64, 98, 23};Arrays.stream(arr).skip(6).forEach(System.out::print); //9823

distinct() 剔除重复元素

        int[] arr = {1, 2, 2, 4, 2};Arrays.stream(arr).distinct().forEach(System.out::print); //124

sorted() ,sorted(Comparator) 将Comparable元素的流排序

        int[] arr = {1, 2, 2, 4, 2};Arrays.stream(arr).sorted().forEach(System.out::print); //12224
        List<Person> list = Arrays.asList(new Person("张三", 18,"2,3"),new Person("李四", 14,"2,3"),new Person("王五", 21,"2,4"));//根据年龄排序 reversed()倒序操作list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).forEach(System.out::println);

peek(fun) 流不变,但会把每个元素传入fun执行,可以用作调试

可以理解为没有返回结果的forEach()

        List<Person> list = Arrays.asList(new Person("张三", 18,"2,3"),new Person("李四", 14,"2,3"),new Person("王五", 21,"2,4"));//根据年龄排序 reversed()倒序操作list.stream().sorted(Comparator.comparing(Person::getAge).reversed()).peek(item->{item.setAge(item.getAge() + 1);}).peek(item->{item.setAge(item.getAge() + 1);}).peek(item->{item.setAge(item.getAge() + 1);}).forEach(System.out::println);结果:
Person(name=王五, age=24, hobbies=2,4)
Person(name=张三, age=21, hobbies=2,3)
Person(name=李四, age=17, hobbies=2,3)

流的Terminal方法(终结操作)

max(Comparator)

min(Comparator)

count()

findFirst() 返回第一个元素

findAny() 返回任意元素

anyMatch(Predicate) ,allMatch(Predicate) ,noneMatch(Predicate)

anyMatch(Predicate)任意元素匹配时返回true

所有元素匹配时返回true

没有元素匹配时返回true

reduce(fun) 从流中计算某个值,接受一个二元函数作为累积器,从前两个元素开始持续应用它,累积器的中间结果作为第一个参数,流元素作为第二个参数

reduce(a, fun) a为幺元值,作为累积器的起点

reduce(a, fun1, fun2)

iterator()

forEach(fun)

forEachOrdered(fun) 可以应用在并行流上以保持元素顺序

toArray()

toArray(T[] :: new) 返回正确的元素类型

collect(Collector)

collect(fun1, fun2, fun3)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91775.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter开发 dart语言基本语法

特点 Dart语言支持JIT与AOT。 Dart语言采用单线程模型。 Dart语言是强类型编程语言&#xff0c;但是允许弱类型语言式编程。 基本语法 1.变量和常量 变量 var、object、dynamic关键字或数据类型显式声明变量。 命名规则&#xff1a; 变量名称必须由数字、字母、下划线或$组成&a…

SpringBoot:基于 Redis 自定义注解实现后端接口防重复提交校验(幂等操作)

SpringBoot&#xff1a;基于 Redis 自定义注解实现后端接口防重复提交校验&#xff08;幂等操作&#xff09;可基于 时间间隔 和 用于幂等判断的参数名称 实现防重复提交校验 客户端发送请求 ↓ [Spring Boot 应用入口]↓ ┌─────────────────────────…

【语音技术】意图与语料

目录 1. 意图 1.1. 意图分类 1.1.1 入口意图&#xff08;Entry Intent&#xff09; 1.1.2 对话意图&#xff08;Dialog Intent&#xff09; 1.2. 意图类型切换操作步骤 2. 语料 2.1 语料分类详解 2.2 语料编写规范详解 2.3 标签符号深度说明 3. 词槽 3.1 符类型要求 …

【MySQL集群架构与实践5】使用Docker实现水平分片

目录 一. 在Docker中安装ShardingSphere 二. 实践&#xff1a;水平分片 2.1 应用场景 2.2 架构图 2.3 服务器规划 2.4 创建server-user容器 2.5 创建server-order0和server-order1容器 2.6.日志配置 2.7 数据节点配置 2.8.测试数据节点 2.8.1.测试server_order0.t_or…

视觉图像处理中级篇 [1]—— 彩色照相机的效果与预处理

在工业检测中&#xff0c;黑白相机虽应用广泛&#xff0c;但在应对颜色差异检测时往往力不从心。彩色照相机凭借其对色彩信息的精准捕捉&#xff0c;成为复杂场景下的理想选择&#xff0c;而预处理技术则进一步释放了其性能潜力。一、彩色照相机的效果检查盖子上的金色标签可以…

使用 BERT 的 NSP 实现语义感知切片 —— 提升 RAG 系统的检索质量

在构建 Retrieval-Augmented Generation&#xff08;RAG&#xff09;系统时&#xff0c;文档的切片方式至关重要。我们需要将长文本切分成合适的段落&#xff08;chunks&#xff09;&#xff0c;然后存入向量数据库进行召回。如果切得太粗&#xff0c;会丢失上下文细节&#xf…

使用STM32CubeMX生成的STM32CubeIDE工程在更改工程名后编译失败问题解决

0 问题描述 使用STM32CubeMX生成STM32CubeIDE工程,然后使用STM32CubeIDE改名后编译提示如下错误: 1 问题原因及解决办法 1.1 问题原因 原因在于更名后STM32CubeIDE没有自动更新引用关系,这是因为我们使用STM32CubeMX生成代码时没有勾选在根目录下生成: 取消勾选在根目…

8月3日星期日今日早报简报微语报早读

8月3日星期日&#xff0c;农历闰六月初十&#xff0c;早报#微语早读。1、广西防城港&#xff1a;奔驰女司机身份已查清&#xff0c;结果将统一对外发布&#xff1b;2、陈艺文、陈佳包揽游泳世锦赛女子跳水三米板金银牌&#xff1b;3、九省份保险业已赔付暴雨灾害损失5.2亿元&am…

wxPython 实践(六)对话框

wxPython 实践&#xff08;一&#xff09;概述 wxPython 实践&#xff08;二&#xff09;基础控件 wxPython 实践&#xff08;三&#xff09;页面布局 wxPython 实践&#xff08;四&#xff09;事件响应 wxPython 实践&#xff08;五&#xff09;高级控件 wxPython 实践&#x…

MATLAB科研数据可视化技术

互联网的飞速发展伴随着海量信息的产生&#xff0c;而海量信息的背后对应的则是海量数据。如何从这些海量数据中获取有价值的信息来供人们学习和工作使用&#xff0c;这就不得不用到大数据挖掘和分析技术。数据可视化分析作为大数据技术的核心一环&#xff0c;其重要性不言而喻…

文明存续的时间博弈:论地球资源枯竭临界期的技术突围与行动紧迫性

摘要当地球资源消耗以指数级速度逼近生态承载力极限&#xff0c;人类文明正面临“存续还是消亡”的终极抉择。本文基于地球资源枯竭的实证数据与技术突破的可行性分析&#xff0c;揭示文明存续的时间窗口已进入不可逆临界期&#xff08;2040-2070年&#xff09;&#xff0c;论证…

Elasticsearch 8.19.0 和 9.1.0 中 LogsDB 和 TSDS 的性能与存储改进

作者&#xff1a;来自 Elastic Martijn Van Groningen 探索 TSDS 和 LogsDB 的最新增强功能&#xff0c;包括优化 I/O、提升合并性能等。 Elasticsearch 带来了许多新功能&#xff0c;帮助你为你的使用场景构建最佳搜索解决方案。通过我们的示例笔记本深入学习&#xff0c;开始…

cs336之注意pytorch的tensor在哪里?(assert的使用)

问题 记住&#xff1a;无论何时你在pytorch中有一个张量tensor&#xff0c;你应该始终问一个问题&#xff1a;它当前位于哪里&#xff1f; 注意它在CPU还是在GPU中。要判断它在哪里&#xff0c;可以使用python的assert断言语句。 assert断言 在 Python 中&#xff0c;assert 是…

Mysql 分区表

分区表是将一张表分成多张独立子表&#xff0c;每个子表是一个区&#xff0c;目的是提高查询效率。 从 server 层来看&#xff0c;只有一张表。但是从引擎层来看&#xff0c;是多张表&#xff0c;对应多个.idb文件。引擎层访问数据只访问特定分区表&#xff0c;也只对特定分区表…

Makefile 入门与实践指南

Makefile 是用于 make 工具的配置文件&#xff0c;它定义了如何编译和链接你的项目&#xff0c;让构建过程自动化。一、核心概念 make 的核心思想是 “目标”&#xff08;Target&#xff09; 和 “依赖”&#xff08;Dependencies&#xff09;&#xff1a; 目标 (Target)&#…

分布式微服务--Nacos作为配置中心(补)关于bosststrap.yml与@RefreshScope

一、关于bosststrap.yml✅ bootstrap.yml 和 application.yml 的区别对比项bootstrap.ymlapplication.yml加载时机优先于 application.yml 加载&#xff08;启动早期&#xff09;程序初始化完成后加载主要用途设置应用的外部配置源、注册中心信息等设置应用内部配置&#xff0c…

[Qt]QString 与Sqlite3 字符串互动[汉字不乱码]

环境&#xff1a;Qt C&#xff08;msvc c&#xff09;1.将与数据库交互的代码文件编码转换为utf-8-bom编码&#xff0c;&#xff08;可使用notepad 进行转换&#xff09;2.在代码文件头文件中加上下面代码。//vs2010 版本是 1600 #if defined(_MSC_VER) && (_MSC_VER &…

SpringBoot启动项目详解

SpringBoot 的启动过程是一个整合 Spring 核心容器、自动配置、嵌入式服务器等功能的复杂流程&#xff0c;核心目标是 “简化配置、快速启动”。下面从入口类开始&#xff0c;逐步拆解其详细启动步骤&#xff1a;一、启动入口&#xff1a;SpringBootApplication与main方法Sprin…

PCB 控深槽如何破解 5G 基站 120℃高热魔咒?

5G 基站在高频通信下的功耗较 4G 基站提升 3-4 倍&#xff0c;射频模块、电源单元等核心部件的工作温度常突破 120℃&#xff0c;远超设备安全阈值&#xff08;≤85℃&#xff09;&#xff0c;形成制约通信稳定性的 “高热魔咒”。印制线路板&#xff08;PCB&#xff09;作为热…

NEXT.js 打包部署到服务器

在网上查了一下&#xff0c;记录一下1.首先执行打包命令&#xff0c;我这个项目是用的pnpm&#xff0c;可以根据项目需求使用 npm 或者别的pnpm run build2.打包完成后会有一个 .next 的文件夹&#xff0c;需要把下图的这些文件放到服务器。服务器需要有node环境之后就需要执行…