网站首页 > 博客文章 正文
在本文中,我们将介绍流,在下一篇文章中,我们将介绍构建 Java 流的十大模式。
首先先看他它是什么?
什么是Stream流
一般来说,流是一些元素的连续序列。
从java的角度讲,Stream是一个接口,如下所示
public interface Stream<T> extends BaseStream<T, Stream<T>> {
}
上面接口说明的是,Stream是类型T的一组元素的系列(可能是有限的或者是无限的),如果是有限的,说明是有界的。
Stream流包含什么
我们通常认为的是,由于Stream代表一组连续的数据流,所以认为stream流保存着数据。但事实并非如此。流不包含任何数据,它从特定来源获取数据,这一点非常重要。
流从数据源获取数据并处理,流只充当数据源到数据目的地之间的管道。
当我们说流有界和无界的时候,其实说的是数据源的有界和无界,如果数据源是有界的,那么Stream就表示一组有界的元素序列,如果数据源是无界的,那么Stream就是无界的,并且表示一组无界得元素序列。
无界并不意味着无限
从java Streams的角度看,无界并不意味着Stream中流动着无限数量的元素,我们通常任务在构建流时不知道数据源数据的数量。
流无界并不意味着它是无限的。只是我们在构建流时不知道数据源数据的大小。
数据源和目的地是什么
数据源和目的地本身就可以是Stream流,我们可以从不同的来源构建流,
我
Source 和 Sink 本身可以是流。我们可以从不同的来源构建 Stream。
另一个需要理解的重点是,Stream流永远不会改变它们从源获取的数据。Stream只是处理来自源的数据并将其发送到目的地。
流管道中的不同阶段
构建 Stream 管道,我们可以将多个操作链接在一起。因此,流管道由多个链接在一起的操作组成。
管道的每个阶段都有几点需要记住。
- 管道中的每个阶段代表一个以指定方式处理数据的操作。
- 作为管道中的一部分,管道中的每个阶段都可能会更改 Stream 的类型。例如,管道中的一个阶段可能会获取Student对象Stream<Student>并给我们一个Stream<Integer>,代表学生的年龄。
- 管道中的每个阶段将处理后的数据发送到管道中的下一个阶段。因此,每个阶段都有一个 目的地,充当管道中下一个阶段的 数据源。
Stream流管道中的操作类型
理解这一点非常重要,因为这里经常出一些重要的面试问题。
Stream管道中有两种类型的操作。
- 中间操作:中间操作表示可以传递到管道中下一个阶段的中间结果。例如,amap()表示以指定方式转换数据的中间操作。Afilter()表示根据指定的Predicate过滤掉数据。Stream管道中可以有很多中间操作。
- 终端操作:终端操作代表管道中的最终任务。例如,forEach()、sum()、count()等。顾名思义,它终止或关闭流管道。因为它关闭了流,所以管道中只能有一个终端操作,即管道的末尾。
Streams 最有亮点的部分是,只有调用终端操作后,整个管道的处理才会开始。这这是面试中经常提出的重要问题之一。
大家可能会问为什么需要Streams?为什么我们不应该直接操作集合对象?原因是 Streams 在处理管道时懒加载,因此占用的内存更少。除非到达终端操作,否则流管道执行不会启动。
在调用终端操作之前,Stream 管道进程不会启动。这使得 Streams 能够拥有轻量级的内存占用。
例如下面的例子
// 这会在输出中给出重复的 deptNo。
// 一个使用peek(),另一个使用forEach()
StudentStream
.map(s -> s.getDeptNo())
.peek(System.out ::println)
.filter(deptNo -> deptNo == 1001 || deptNo = = 1002)
.forEach(System.out :: println);
map(),filter()和peek()是中间操作,forEach()是终端操作。在执行该方法之前,流处理不会执行。
我们如何证明这一点?
在两者之间有一个 peek() 方法。这是一个中间操作。按原样执行上面的代码片段将会看到输出。但删除最后一个操作 forEach() 运行。尽管该方法正在打印元素,但它不显示任何输出。原因是该方法只是一个中间操作,直到调用forEach()这个终端操作为止才会运行。
// 不会输出
studentStream
.map(s -> s.getDeptNo())
.peek(System.out::println)
.filter(deptNo -> deptNo == 1001 || deptNo == 1002)
我们如何知道操作是中间操作还是终端操作?
第一个信息来源是查看 Java 文档。或者还有一个小技巧可以了解这一点:任何返回 Stream 的调用或操作都是中间调用。任何返回 Stream 对象或 void 之外的内容的调用都是触发处理的终端调用。
因此,例如map()和filter()返回Stream对象是中间操作。该forEach()方法返回void、sum()返回int/long,因此,都是终端操作。
这就是本文的全部内容。在下一篇文章中,我们将研究构建流的不同方法。
总结
- 在 Java 中, TStream是一个类型接口,表示类型的元素序列。
- 如果Stream包含有限元素,则称其为有界;如果不表示有限数量的元素,则称其为无界。
- Stream不包含任何数据。
- 流永远不会改变它们从源获取的数据。他们只是处理来自源的数据并将其发送到接收器。
- Stream 管道中执行的操作有两种类型:中间操作和终端操作。
- 中间操作返回表示中间结果的另一个流对象。
猜你喜欢
- 2024-12-26 Java 8 Stream 处理大数据集:实战与优化
- 2024-12-26 面试官:Java8 lambda 表达式 forEach 如何提前终止?
- 2024-12-26 Javascript中,forEach和map到底有什么区别?
- 2024-12-26 Excel VBA之For Each遍历循环的应用
- 2024-12-26 为什么建议使用 for…of 循环而不是 foreach 循环呢
- 2024-12-26 前端开发map和foreach区别,map遍历方式用法介绍
- 2024-12-26 Rust语言从入门到精通系列 - 零基础掌握Stream流迭代器
- 2024-12-26 Map遍历的四种方法效率对比
- 2024-12-26 java集合类之java中集合类有哪些?如何分类?
- 2024-12-26 【一分钟学Java】之List
你 发表评论:
欢迎- 367℃用AI Agent治理微服务的复杂性问题|QCon
- 358℃初次使用IntelliJ IDEA新建Maven项目
- 356℃手把手教程「JavaWeb」优雅的SpringMvc+Mybatis整合之路
- 351℃Maven技术方案最全手册(mavena)
- 348℃安利Touch Bar 专属应用,让闲置的Touch Bar活跃起来!
- 346℃InfoQ 2024 年趋势报告:架构篇(infoq+2024+年趋势报告:架构篇分析)
- 345℃IntelliJ IDEA 2018版本和2022版本创建 Maven 项目对比
- 342℃从头搭建 IntelliJ IDEA 环境(intellij idea建包)
- 最近发表
- 标签列表
-
- powershellfor (55)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)