Java8实战-总结23

Java8实战-总结23

  • 使用流
    • 构建流
      • 由值创建流
      • 由数组创建流
      • 由文件生成流
      • 由函数生成流:创建无限流
    • 小结

使用流

构建流

流对于表达数据处理查询是非常强大而有用的。到目前为止,已经能够使用stream方法从集合生成流了。此外,还介绍了如何根据数值范围创建数值流。下面会介绍如何从值序列、数组、文件来创建流,甚至由生成函数来创建无限流。

由值创建流

可以使用静态方法Stream.of,通过显式值创建一个流。它可以接受任意数量的参数。例如,以下代码直接使用Stream.of创建了一个字符串流。然后,可以将字符串转换为大写,再一个个打印出来:

Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);

可以使用empty得到一个空流,如下所示:

Stream<String> emptyStream = Stream.empty();

由数组创建流

可以使用静态方法Arrays.stream从数组创建一个流。它接受一个数组作为参数。例如,可以将一个原始类型int的数组转换成一个IntStream,如下所示:

int[] numbers ={2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum();//总和是41

由文件生成流

Java中用于处理文件等I/O操作的NIO API(非阻塞I/O)已更新,以便利用Stream APIjava.nio.file.Files中的很多静态方法都会返回一个流。例如,一个很有用的方法是Files.lines,它会返回一个由指定文件中的各行构成的字符串流。可以用这个方法看看一个文件中有多少各不相同的词:

long uniqueWords = 0;
try(Stream<String> lines =Files.lines(Paths.get("data.txt"), Charset.defaultCharset ())) {//流会自动关闭uniqueWords = lines.flatMap(line -> Arrays.stream(line.split("")))//生成单词流.distinct()//删除重复项.count();//数一数有多少各不相同的单词
}
catch(IOException e) {//如果打开文件时出现异常则加以处理
}

可以使用Files.lines得到一个流,其中的每个元素都是给定文件中的一行。然后,可以对line调用split方法将行拆分成单词。应该注意的是,该如何使用flatMap产生一个扁平的单词流,而不是给每一行生成一个单词流。最后,把distinctcount方法链接起来,数数流中有多少各不相同的单词。

由函数生成流:创建无限流

Stream API提供了两个静态方法来从函数生成流:Stream.iteratestream.generate。这两个操作可以创建所谓的无限流:不像从固定集合创建的流那样有固定大小的流。由iterategenerate产生的流会用给定的函数按需创建值,因此可以无穷无尽地计算下去。一般来说,应该使用limit(n)来对这种流加以限制,以避免打印无穷多个值。

  1. 迭代

一个iterate的简单例子:

Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);

iterate方法接受一个初始值(在这里是0),还有一个依次应用在每个产生的新值上的Lambda(Unaryoperator<t>类型)。这里,使用Lambda n -> n +2,返回的是前一个元素加上2。因此,iterate方法生成了一个所有正偶数的流:流的第一个元素是初始值0。然后加上2来生成新的值2,再加上2来得到新的值4,以此类推。这种iterate操作基本上是顺序的,因为结果取决于前一次应用。此操作将生成一个无限流——这个流没有结尾,因为值是按需计算的,可以永远计算下去。这个流是无界的。这是流和集合之间的一个关键区别。使用limit方法来显式限制流的大小。这里只选择了前10个偶数。然后可以调用forEach终端操作来消费流,并分别打印每个元素。

一般来说,在需要依次生成一系列值的时候应该使用iterate,比如一系列日期:1月31日,2月1日,依此类推。

  1. 生成

iterate方法类似,generate方法也可按需生成一个无限流。但generate不是依次对每个新生成的值应用函数的。它接受一个supplier<T>类型的Lambda提供新的值。先来看一个简单的用法:

Stream.generate(Math::random).limit(5).forEach(System.out::println);

这段代码将生成一个流,其中有五个01之间的随机双精度数。例如,运行一次得到了下面的结果:

0.9410810294106129
0.6586270755634592
0.9592859117266873
0.13743396659487006
0.3942776037651241

Math.Random静态方法被用作新值生成器。同样,可以用limit方法显式限制流的大小,否则流将会无限长。

使用的供应源(指向Math.random的方法引用)是无状态的:它不会在任何地方记录任何值,以备以后计算使用。但供应源不一定是无状态的。可以创建存储状态的供应源,它可以修改状态,并在为流生成下一个值时使用。但很重要的一点是,在并行代码中使用有状态的供应源是不安全的。因此下面的代码仅仅是为了内容完整,应尽量避免使用。

在这个例子中会使用IntStream说明避免装箱操作的代码。IntStreamgenerate方法会接受一个IntSupplier,而不是Supplier<t>。例如,可以这样来生成一个全是1的无限流:

IntStream ones = IntStream.generate(() -> 1);

Lambda允许创建函数式接口的实例,只要直接内联提供方法的实现就可以。也可以像下面这样,通过实现IntSupplier接口中定义的getAsInt方法显式传递一个对象:

IntStream twos = IntStream.generate(new IntSupplier() {public int getAsInt()	{return 2;}
});

generate方法将使用给定的供应源,并反复调用getAsInt方法,而这个方法总是返回2。但这里使用的匿名类和Lambda的区别在于,匿名类可以通过字段定义状态,而状态又可以用getAsInt方法来修改。这是一个副作用的例子。迄今见过的所有Lambda都是没有副作用的;它们没有改变任何状态。

回到斐波纳契数列的任务上,现在需要做的是建立一个IntSupplier,它要把前一项的值保存在状态中,以便getAsInt用它来计算下一项。此外,在下一次调用它的时候,还要更新IntSupplier的状态。下面的代码就是如何创建一个在调用时返回下一个斐波纳契项的IntSupplier:

IntSupplier fib = new IntSupplier() {private int previous = 0;private int current = 1;public int getAsInt () {int oldPrevious = this.previous;int nextValue = this.previous + this.current;this.previous = this.current;this.current = nextValue;return oldPrevious;}
};
IntStream.generate(fib).limit(10).forEach(System.out::println);

前面的代码创建了一个IntSupplier的实例。此对象有可变的状态:它在两个实例变量中记录了前一个斐波纳契项和当前的斐波纳契项。getAsInt在调用时会改变对象的状态,由此在每次调用时产生新的值。相比之下,使用iterate的方法则是纯粹不变的:它没有修改现有状态,但在每次迭代时会创建新的元组。

小结

现在可以更高效地处理集合了。流让你可以简洁地表达复杂的数据处理查询。此外,流可以透明地并行化。以下是关键概念。

  • Streams API可以表达复杂的数据处理查询。
  • 可以使用filterdistinctskiplimit对流做筛选和切片。
  • 可以使用mapflatMap提取或转换流中的元素。
  • 可以使用findFirstfindAny方法查找流中的元素。
  • 可以用allMatchnoneMatchanyMatch方法让流匹配给定的谓词。
  • 这些方法都利用了短路:找到结果就立即停止计算;没有必要处理整个流。
  • 可以利用reduce方法将流中所有的元素迭代合并成一个结果,例如求和或查找最大元素。
  • filtermap等操作是无状态的,它们并不存储任何状态。reduce等操作要存储状态才能计算出一个值。sorteddistinct等操作也要存储状态,因为它们需要把流中的所有元素缓存起来才能返回一个新的流。这种操作称为有状态操作。
  • 流有三种基本的原始类型特化:IntStreamDoubleStreamLongStream。它们的操作也有相应的特化。
  • 流不仅可以从集合创建,也可从值、数组、文件以及iterategenerate等特定方法创建。
  • 无限流是没有固定大小的流。
    156

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

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

相关文章

docker搭建个人网盘和私有仓库Harbor

目录 1、使用mysql:5.7和 owncloud 镜像&#xff0c;构建一个个人网盘 2、安装搭建私有仓库 Harbor 1、使用mysql:5.7和owncloud&#xff0c;构建一个个人网盘 1.拉取mysql:5.6镜像&#xff0c;并且运行mysql容器 [rootnode8 ~]# docker pull mysql:5.7 [rootnode8 ~]# doc…

Excel VSTO开发10 -自定义任务面板

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 10 自定义任务面板 自定义任务面板&#xff08;有些地方称为侧边面板&#xff09;即CustomTaskPane&#xff0c;这个类在Microsoft…

代码随想录二刷day15

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣102. 二叉树的层序遍历二、力扣107. 二叉树的层序遍历 II三、力扣199. 二叉树的右视图四、力扣637. 二叉树的层平均值五、力扣429. N 叉树的层序遍历六…

leetcode 第 361 场周赛

2843. 统计对称整数的数目 核心思想&#xff1a;枚举每一个数是否是对称整数,第一种写法为python写法&#xff0c;第二种为一般写法我觉得更好&#xff0c;非常有思想性。 2844. 生成特殊数字的最少操作 核心思想&#xff1a;枚举特殊数字结尾的几种可能。其实自己做的时候一…

2023/09/07 c++qt day2

#include <iostream>using namespace std; //封装一个学生类 struct stu { private://存放学生的成绩int stu_score[256];//记录学生个数int stu_num; public://用于设置学生个数void setNum(){cout<<"请输入学生的个数"<<" ";cin>&g…

Stable Diffuse 之 本地环境部署 WebUI 进行汉化操作

Stable Diffuse 之 本地环境部署 WebUI 进行汉化操作 目录 Stable Diffuse 之 本地环境部署 WebUI 进行汉化操作 一、简单介绍 二、汉化操作 附录&#xff1a; 一、Install from URL 中出现 Failed to connect to 127.0.0.1 port 7890: Connection refused 错误&#xf…

蓝桥杯练习题(3的倍数)

问题描述 小蓝对 3 的倍数很感兴趣。现在他手头有三个不同的数 a,b,c, 他想知道, 这三个数中是不是有两个数的和是 3 的倍数。 例如, 当 a3,b4,c6 时, 可以找到 a 和 c 的和是 3 的倍数。 例如, 当 a3,b4,c7 时, 没办法找到两个数的和是 3 的倍数。 输入格式 输入三行, 每行…

vscode ros配置

【ROS】VSCODE ROS 配置方法&#xff08;保姆级教程&#xff0c;总结了多篇&#xff09;_ros vscode_晴明大大的博客-CSDN博客

网络编程、多路复用和多路并发的区别、

在网络编程中&#xff0c;多路复用&#xff08;Multiplexing&#xff09;和多路并发&#xff08;Multithreading/Multiprocessing&#xff09;是两种不同的技术&#xff0c;用于处理多个客户端连接。它们有以下区别&#xff1a; 1.多路复用&#xff08;Multiplexing&#xff0…

【2023高教社杯数学建模国赛】ABCD题 问题分析、模型建立、参考文献及实现代码

【2023高教社杯数学建模国赛】ABCD题 问题分析、模型建立、参考文献及实现代码 1 比赛时间 北京时间&#xff1a;2023年9月7日 18:00-2023年9月10日20:00 2 思路内容 可以参考我提供的历史竞赛信息内容&#xff0c;最新更新我会发布在博客和知乎上&#xff0c;请关注我获得最…

重写与重载笔记

方法的重载(overload)&#xff1a;---------------------大大简化方法的调用 发生在同一类中&#xff0c;方法名相同&#xff0c;参数列表不同,方法的重载与返回值类型无关编译器在编译时会根据方法的签名自动绑定调用的方法 重写&#xff1a; 发生在父子类中&#xff0c;方法名…

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(9 月 6 日论文合集)

文章目录 一、分割|语义相关(19篇)1.1 DCP-Net: A Distributed Collaborative Perception Network for Remote Sensing Semantic Segmentation1.2 Self-Supervised Pre-Training Boosts Semantic Scene Segmentation on LiDAR data1.3 DeNISE: Deep Networks for Improved Segm…

C++核心编程--类篇

C核心编程 1.内存分区模型 C程序在执行时&#xff0c;将内存大方向分为4个区域 意义&#xff1a;不同区域存放数据&#xff0c;赋予不同的生命周期&#xff0c;更能灵活编程 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的全局区&#xff1a;存放…

Vue3+Element Plus实现el-table跨行显示(非脚手架)

Vue3Element Plus实现el-table跨行显示 app组件内容使用:span-method"objectSpanMethod"自定义方法实现跨行显示查询方法初始化挂载新建一个html即可进行测试&#xff0c;完整代码如下效果图 app组件内容 <div id"app"><!-- 远程搜索 --><e…

算法训练day43|动态规划 part05:0-1背包 (LeetCode 1049. 最后一块石头的重量 II、494. 目标和、474.一和零)

文章目录 1049. 最后一块石头的重量 II思路分析代码实现 494. 目标和思路分析动规方法代码实现总结思考 474.一和零思路分析代码实现思考总结 var code "57a5e730-4e5e-43ad-b567-720d69f0371a"1049. 最后一块石头的重量 II 题目链接&#x1f525;&#x1f525; 有…

揭秘拼多多API接口:让商家和用户实现高效连接与便捷操作

随着电商行业的飞速发展&#xff0c;拼多多作为一家新兴电商平台&#xff0c;近年来已逐渐成为市场的焦点。为了满足商家和用户的需求&#xff0c;拼多多不断创新&#xff0c;推出了智能化的API接口&#xff0c;以实现更加高效、便捷的操作和管理。本文将深入探讨拼多多API接口…

提高使用VS Code工作效率的技巧

提高使用VS Code工作效率的技巧 时间轴视图&#xff1a;本地源代码控制 时间轴视图为我们提供了内置的源代码控制。 我们中的许多人都知道 Git 和其他源代码控制工具有多么有用&#xff0c;它们可以帮助我们轻松跟踪文件更改并在需要时恢复到之前的状态。 因此&#xff0c;…

MySQL数据库——基础篇总结(概述、SQL、函数、约束、多表查询、事务)

目录 概述 概念 MySQL启动与停止 客户端连接 关系型数据库&#xff08;RDBMS&#xff09; SQL 数据类型 DDL DML DQL DCL 函数 字符串函数 数值函数 日期函数 流程函数 约束 多表查询 多表关系 笛卡尔积 内连接 外连接 自连接 联合查询 子查询 事…

LeetCode 面试题 03.05. 栈排序

文章目录 一、题目二、C# 题解 一、题目 栈排序。 编写程序&#xff0c;对栈进行排序使最小元素位于栈顶。最多只能使用一个其他的临时栈存放数据&#xff0c;但不得将元素复制到别的数据结构&#xff08;如数组&#xff09;中。该栈支持如下操作&#xff1a;push、pop、peek 和…

go基础08-map的内部实现

和切片相比&#xff0c;map类型的内部实现要复杂得多。Go运行时使用一张哈希表来实现抽象的map类型。运行时实现了map操作的所有功能&#xff0c;包括查找、插入、删除、遍历等。在编译阶段&#xff0c;Go编译器会将语法层面的map操作重写成运行时对应的函数调用。 下面是大致的…