什么是Stream流

文章目录

    • 一、创建流
      • 1.1 流的类型
      • 1.2 创建 Stream 的常见操作
    • 二、 中间操作
      • 2.1 流的映射
      • 2.2 流的过滤
      • 2.3 其他中间操作
    • 三、 终端操作
      • 3.1 reduce() 的使用方法
      • 3.2 *short-circuiting* 方法
      • 3.3 其他的终端操作
    • 参考资料

一、创建流

1.1 流的类型

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

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

stream() 方法在 Collection接口

1.2 创建 Stream 的常见操作

举个例子,以 stream() 函数为例,可以通过集合、数组、I/O 通道等方式创建流。

//  从 List 创建流
List<String> list = Arrays.asList("apple", "banana", "orange");
Stream<String> streamFromList = list.stream();// 从数组创建 IntStream:
int[] array = {1, 2, 3, 4, 5};
IntStream streamFromArray = Arrays.stream(array);// 使用 Stream.of 创建流:
Stream<String> streamFromValues = Stream.of("apple", "banana", "orange");

事实上,创建流还有很多方式,更多细节查看 Creating Streams - Dev.java


二、 中间操作

中间操作是 map-filter-reduce 算法中 map 和 filter 实现。

中间操作会返回一个新的 Stream,因此可以链式调用。这些操作是惰性的,即它们不会立即执行,而是在有终端操作时才会执行。这意味着中间操作只是定义了流的转换规则,实际处理会推迟到终端操作执行时。

具体细节查看 Reducing a Stream - Dev.java

2.1 流的映射

(1) map()

映射流包括使用Function转换其元素。

您可以使用 map() 方法将一个流映射到另一个流,该方法将Function作为参数。映射流意味着该流处理的所有元素都将使用Function进行转换。举个例子,示例代码如下:

List<String> strings = List.of("one", "two", "three", "four");
Function<String, Integer> toLength = String::length;
Stream<Integer> ints = strings.stream().map(toLength);

需要注意的是,这段代码里面没有终端操作,因此这段代码没有做任何事

另外,有三种方法可以从 Stream 转到原始类型的流:mapToInt(), mapToLong() and mapToDouble()。举个例子,示例代码如下:

List<String> strings = List.of("one", "two", "three", "four");
IntSummaryStatistics stats = strings.stream().mapToInt(String::length).summaryStatistics();
System.out.println("stats = " + stats);

输出结果为

 stats = IntSummaryStatistics{count=4, sum=15, min=3, average=3,750000, max=5}

(2)flatmap()

在 Java 中,flatMap() 是流(Stream)类的一个中间操作,用于处理包含多个元素的流。它的作用是将每个流元素映射为一个流,然后将这些流合并成一个新的流

举个例子,假设有一个列表,其中包含多个单词,我们希望将每个单词拆分为字符,并将所有字符合并到一个新的流中:

List<String> words = Arrays.asList("Hello", "World");// 使用 flatMap 将每个单词拆分为字符,并合并为一个新流
List<String> characters = words.stream().flatMap(word -> Arrays.stream(word.split(""))).collect(Collectors.toList());System.out.println(characters);

在这个例子中,flatMap 将每个单词映射为一个字符流,然后将这些字符流合并成一个新的流,最终得到一个包含所有字符的列表。输出结果为:

[H, e, l, l, o, W, o, r, l, d]

2.2 流的过滤

过滤是在流(Stream)上进行元素过滤。此方法适用于对象流和原始类型流。

举个例子,

List<String> strings = List.of("one", "two", "three", "four");
long count = strings.stream().map(String::length).filter(length -> length == 3).count();
System.out.println("count = " + count);   // 结果为:count = 2

其中,count()是 Stream API的另一个终端操作,它只计算已处理元素的数量

2.3 其他中间操作

  • distinct()方法 : 使用hashCode()和equals()方法来发现重复项, 然后去除重复项

  • sorted(): 有一个comparator的重载,该比较器将用于比较和排序流的元素。如果您不提供比较器,则Stream API假定您的流的元素具有可比性。如果不是,则会引发ClassCastException。

  • skip(long n) 方法: 用于跳过流中的前 n 个元素,返回一个新的流。如果流的长度小于 n,则返回一个空流。

  • limit(long maxSize) 方法: 用于限制流的大小,返回一个包含不超过 maxSize 个元素的新流。

  • concat() : 用于连接两个流,将它们合并成一个新的流。 建议用 flatMap() 来替代这个函数,举个例子:

    List<Integer> list0 = List.of(1, 2, 3);
    List<Integer> list1 = List.of(4, 5, 6);
    List<Integer> list2 = List.of(7, 8, 9);// 1st pattern: concat
    List<Integer> concat = Stream.concat(list0.stream(), list1.stream()).collect(Collectors.toList());// 2nd pattern: flatMap
    List<Integer> flatMap =Stream.of(list0.stream(), list1.stream(), list2.stream()).flatMap(Function.identity()).collect(Collectors.toList());System.out.println("concat  = " + concat);
    System.out.println("flatMap = " + flatMap);
    
  • peek(): ,用于对流中的每个元素执行操作,同时保持流的原始结构。它返回的流与原始流相同,但可以在执行 peek() 时观察到中间的操作。这个可以用来调试流

    List<String> strings = List.of("one", "two", "three", "four");
    List<String> result =strings.stream().peek(s -> System.out.println("Starting with = " + s)).filter(s -> s.startsWith("t")).peek(s -> System.out.println("Filtered = " + s)).map(String::toUpperCase).peek(s -> System.out.println("Mapped = " + s)).collect(Collectors.toList());
    System.out.println("result = " + result);
    

三、 终端操作

终端操作(Terminal Operations)是 map-filter-reduce 算法中 reduce 实现。

终端操作(Terminal Operations)是流操作中的最后一步,它们产生最终的结果或副作用。终端操作会触发流的遍历,并生成最终的结果或执行一些操作。在执行后,流就会被消耗,不能再使用。

如果流不以终端操作结束,则流不会处理任何数据。

3.1 reduce() 的使用方法

reduce() 方法: 对流中的元素进行归约操作,返回一个 Optional。(官方不建议使用这个方法)例如:

Optional<String> concatenated = words.stream().reduce((s1, s2) -> s1 + ", " + s2);

具体细节查看:Reducing a Stream - Dev.java

3.2 short-circuiting 方法

“short-circuiting” 方法是指在处理流时,当满足某个条件后,不再继续处理剩余的元素,提前结束处理流的过程。这可以帮助提高性能,因为它避免了对整个流的遍历。

在 Java 的 Stream API 中,有一些操作是 short-circuiting 的,例如:

  1. findFirst(): 返回第一个符合条件的元素后,立即结束流的处理。
  2. findAny(): 返回任意符合条件的元素后,立即结束流的处理。
  3. limit(n): 限制流的大小为 n,一旦达到这个大小,就不再继续处理。
  4. anyMatch(predicate): 一旦有任意一个元素满足条件,就结束流的处理。
  5. allMatch(predicate): 一旦有任意一个元素不满足条件,就结束流的处理。
  6. noneMatch(predicate): 一旦有任意一个元素满足条件,就结束流的处理。

3.3 其他的终端操作

需要注意的是,尽量避免使用 reduce() 方法

以下是一些常见的终端操作:

  1. forEach(): 对流中的每个元素执行指定的操作。例如:

    codeList<String> words = Arrays.asList("apple", "banana", "orange");
    words.stream().forEach(System.out::println);
    
  2. count(): 返回流中元素的数量。例如:

    long count = words.stream().count();
    
  3. collect(): 将流中的元素收集到一个集合或其他数据结构中。例如:

    List<String> collectedList = words.stream().collect(Collectors.toList());
    
  4. min() 和 max(): 返回流中的最小或最大元素。例如:

    Optional<String> minElement = words.stream().min(String::compareTo);
    Optional<String> maxElement = words.stream().max(String::compareTo);
    
  5. anyMatch()、allMatch() 和 noneMatch(): 用于检查流中的元素是否匹配给定的条件。例如:

    codeboolean anyMatch = words.stream().anyMatch(s -> s.startsWith("a"));
    boolean allMatch = words.stream().allMatch(s -> s.length() > 3);
    boolean noneMatch = words.stream().noneMatch(s -> s.contains("z"));
    

具体细节查看 Adding a Terminal Operation on a Stream - Dev.java


参考资料

Stream - Dev.java

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

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

相关文章

Socks5代理为何比HTTP代理快?

在网络世界中&#xff0c;代理服务器扮演着重要的角色&#xff0c;它们能够帮助我们访问被限制的网站、提高网络安全性以及优化网络性能。其中&#xff0c;Socks5代理和HTTP代理是两种常见的代理类型。然而&#xff0c;很多用户发现&#xff0c;相较于HTTP代理&#xff0c;Sock…

awk和xargs指令

ps -ef|grep "pytest"|awk {print $2}|xargs kill-9解释&#xff1a; ps -ef|grep “pytest”&#xff1a;表示找到pytest进程awk ‘{print $2}’&#xff1a;表示将第二个域打印出来&#xff0c;这里显示的就是进程号xargs kill-9&#xff1a;表示将前面的输出结果…

【两大3D转换SDK对比】HOOPS Exchange VS. CAD Exchanger

在现代工业和工程设计领域&#xff0c;CAD数据转换工具是确保不同软件系统间数据互通的关键环节。HOOPS Exchange和CAD Exchanger是两款备受关注的工具&#xff0c;它们在功能、支持格式、性能和应用场景等方面有着显著差异。 本文将从背景、支持格式、功能和性能、应用场景等…

MySQL 条件函数/加密函数/转换函数

条件函数 IF(): 如果条件为真&#xff0c;返回一个值&#xff0c;否则返回另一个值。 -- 示例&#xff1a;根据员工的薪水返回薪水等级 SELECT name, salary, IF(salary < 3000, Low, IF(salary BETWEEN 3000 AND 7000, Medium, High)) AS salary_level FROM employ…

嵌入式ARM控制器在AGV里的应用

随着ARM技术以及芯片加工工艺的迅猛发展&#xff0c; ARM工业计算机得到了越来越广泛的应用&#xff0c;尤其在工业智慧城市、智能设备以及工业自动化控制等领域。本文将为大家详细介绍ARM控制器在AGV控制系统中的应用&#xff0c;来供大家学习和参考&#xff0c;欢迎大家一起来…

Linux磁盘-创建分区

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux磁盘涉及到的命令不是很多&#xff0c;但是在实际运维中的作用却很大&#xff0c;因为Linux系统及业务都会承载到硬盘…

2.6 计算机语言

声明&#xff1a;文章参考的《系统架构设计师教程&#xff08;第二版&#xff09;》&#xff0c;如有侵权&#xff0c;本人将立即修改和删除。 一、计算机语言的组成 计算机语言主要由一套指令组成。 指令包括表达式&#xff08;变量、常量、字面量、运算符&#xff09;、流程…

【PTA天梯赛】L1-003 个位数统计(15分)

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法刷题 &#x1f43e;或许会很慢&#xff0c;但是不可以停下来&#x1f43e; 文章目录 题目题解总结 题目 题目链接 题解 使用string把长度达1000位的数字存起来开一个代表个位数的数组 a[11]倒序计算最后一位&#xff0c;…

进度条提示-在python程序中使用避免我误以为挂掉了

使用库tqdm 你还可以手写一点&#xff0c;反正只要是输出点什么东西都可以&#xff1b; Demo from chatgpt import time from tqdm import tqdm# 示例函数&#xff0c;模拟长时间运行的任务 def long_running_task():total_steps 100for step in tqdm(range(total_steps), …

js 格式化时间

方法一&#xff1a;使用toLocaleString或toLocaleDateString/toLocaleTimeString Date对象提供了toLocaleString()、toLocaleDateString()和toLocaleTimeString()方法&#xff0c;这些方法允许你根据本地时间格式来显示日期和时间。虽然它们不直接提供高度自定义的格式选项&am…

mac下mysql无法登陆的问题

用如下命令登录出现错误。 sudo mysql.server start解决方案 使用如下命令登录 sudo /usr/local/MySQL/support-files/mysql.server start

利用 Plotly.js 创建交互式条形图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 利用 Plotly.js 创建交互式条形图 应用场景介绍 交互式条形图广泛应用于数据可视化和分析领域。它可以直观地展示不同类别或分组之间的数值差异&#xff0c;并允许用户通过交互操作探索数据。 代码基本功能介…

基于springboot+mybatis学生管理系统

基于springbootmybatis学生管理系统 简介&#xff1a; 题目虽然是学生管理系统&#xff0c;但功能包含(学生&#xff0c;教师&#xff0c;管理员),项目基于springboot2.1.x实现的管理系统。 编译环境 &#xff1a; jdk 1.8 mysql 5.5 tomcat 7 框架 &#xff1a; springboot…

RISC-V指令集架构详细组成

寄存器组成 寄存器&#xff1a;用于暂存待处理的数据。 RISC-V架构具有一组统一的寄存器&#xff0c;用于整数运算和地址计算&#xff0c;具体如下&#xff1a; 通用寄存器 x0&#xff1a;存数值0.x1-x31&#xff1a;通用目的寄存器。每个寄存器都是32位&#xff08;RV32I&a…

代码随想录第50天|单调栈

739. 每日温度 参考 思路1: 暴力解法 思路2: 单调栈 使用场合: 寻找任一个元素的右边或者左边第一个比自己大或者小的元素位置, 存放的是遍历过的元素 记忆: 单调栈是对遍历过的元素做记录, 一般是对栈顶的元素 nums[mystack.top()] 做赋值操作的 如果想找到右边的元素大于左…

ccf认证 202312-3

小 C 观察了事先收集到的数据&#xff0c;并加以统计&#xff0c;得到了一个名词属于各个类别的可能性大小的信息。具体而言&#xff0c;每个类别都可以赋予一个被称为权重的值&#xff0c;值越大&#xff0c;说明一个名词属于该类别的可能性越大。由于每次向用户的询问可以获得…

力扣题解(摆动序列)

376. 摆动序列 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为 摆动序列 。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。 例如&#xff0c; [1, 7, 4, 9, 2, 5] 是一个 …

TCP和IP数据包结构

一、问题引入 一般我们在谈上网速度的时候&#xff0c;专业上用带宽来描述&#xff0c;其实无论说网速或者带宽都是不准确的&#xff0c;呵呵。比如&#xff1a;1兆&#xff0c;512K……有些在学校的学生&#xff0c;也许会有疑问&#xff0c;明明我的业务是1M&#xff0c;为…

51单片机(STC8051U34K64)_RA8889_SPI4参考代码(v1.3)

硬件&#xff1a;STC8051U34K64 RA8889开发板&#xff08;硬件跳线变更为SPI-4模式&#xff0c;PS101&#xff0c;R143&#xff0c;R141短接&#xff0c;R142不接&#xff09; STC8051U34K64是STC最新推出来的单片机&#xff0c;主要用于替换传统的8051单片机&#xff0c;与标…

程序员学长 | 快速学习一个算法,GAN

本文来源公众号“程序员学长”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;快速学习一个算法&#xff0c;GAN GAN 如何工作&#xff1f; GAN 由两个部分组成&#xff1a;生成器&#xff08;Generator&#xff09;和判别器&…