流与装饰器

几年前, Streams API随lambda表达式一起在Java 8中引入。 作为一个熟练的Java专家,我尝试在我的一些项目中使用此新功能,例如here和here 。 我不是很喜欢它,然后又回到了好的老房子里。 此外,我创建了装饰库Cactoos来取代Guava ,而Guava在很多地方都不是很好。

这是一个原始示例。 假设我们有一些来自某些数据源的测量值,它们都是零到一之间的数字:

Iterable<Double> probes;

现在,我们只需要显示其中的前10个,忽略零和一,然后将它们重新缩放为(0..100) 。 听起来很容易,对吧? 有三种方法可以实现:过程式,面向对象和Java 8方法。 让我们从过程的方式开始:

int pos = 0;
for (Double probe : probes) {if (probe == 0.0d || probe == 1.0d) {continue;}if (++pos > 10) {break;}System.out.printf("Probe #%d: %f", pos, probe * 100.0d);
}

为什么这是一种程序方式? 因为这势在必行。 为什么势在必行? 因为它是程序性的。 不,我在开玩笑。

这是当务之急,因为我们正在向计算机发出有关将哪些数据放入何处以及如何对其进行迭代的指令。 我们不是在声明结果,而是必须构建它。 它可以工作,但不是真正可扩展的。 我们无法参与该算法并将其应用于另一个用例。 我们不能真正轻松地对其进行修改,例如从两个来源而不是一个来源获取数字,等等。这是程序性的。 说够了。 不要这样

现在,Java 8为我们提供了Streams API ,该API应该提供一种实现此目的的功能方法。 让我们尝试使用它。

首先,我们需要创建一个Stream的实例, Iterable 不允许我们直接获取它。 然后,我们使用流API来完成这项工作:

StreamSupport.stream(probes.spliterator(), false).filter(p -> p == 0.0d || p == 1.0d).limit(10L).forEach(probe -> System.out.printf("Probe #%d: %f", 0, probe * 100.0d));

这将起作用,但是将对所有探针说出Probe #0 ,因为forEach()不适用于索引。 目前是没有这样的事forEachWithIndex()Stream界面的Java 8(和Java 9的太 )。 这是使用原子计数器的解决方法 :

AtomicInteger index = new AtomicInteger();
StreamSupport.stream(probes.spliterator(), false).filter(probe -> probe == 0.0d || probe == 1.0d).limit(10L).forEach(probe -> System.out.printf("Probe #%d: %f",index.getAndIncrement(),probe * 100.0d));

“那是怎么了?” 你可能会问。 首先,看看在Stream接口中找不到正确的方法时,我们遇到麻烦的Stream 。 我们立即摆脱了“流式”范式,回到了良好的旧程序全局变量(计数器)。 其次,我们真的看不到那些filter()limit()forEach()方法内部发生了什么。 它们如何工作? 该文档说,这种方法是“声明性的”,并且Stream接口中的每个方法都返回某个类的实例。 他们是什么班? 只看这段代码,我们一无所知。

此流API的最大问题是接口Stream,它非常庞大!

这两个问题是联系在一起的。 此流API的最大问题是接口Stream –很大。 在撰写本文时,有43种方法。 在单个界面中四十三! 从SOLID到后来的更严格的原则 ,这都违反了面向对象编程的每一个原则 。

实现相同算法的面向对象方式是什么? 这就是我如何用Cactoos做到的 ,这只是一个集合 原始 简单的Java类:

new And(new Mapped<Double, Scalar<Boolean>>(new Limited<Double>(new Filtered<Double>(probes,probe -> probe == 0.0d || probe == 1.0d),10),probe -> () -> {System.out.printf("Probe #%d: %f", 0, probe * 100.0d);return true;}),
).value();

让我们看看这里发生了什么。 首先, Filtered装饰了我们的可迭代probes以从中取出某些项。 注意, Filtered实现了Iterable 。 然后, Limited (也是一个Iterable )仅取出前十个项目。 然后, Mapped将每个探针转换为Scalar<Boolean>的实例,该实例执行行打印。

最后, And的实例遍历“标量”列表,并要求每个标量返回boolean 。 他们打印行并返回true 。 由于它是trueAnd使用下一个标量进行下一次尝试。 最后,其方法value()返回true

但是,等等,没有索引。 让我们添加它们。 为了做到这一点,我们仅使用另一个名为AndWithIndex类:

new AndWithIndex(new Mapped<Double, Func<Integer, Boolean>>(new Limited<Double>(new Filtered<Double>(probes,probe -> probe == 0.0d || probe == 1.0d),10),probe -> index -> {System.out.printf("Probe #%d: %f", index, probe * 100.0d);return true;}),
).value();

现在,我们将探针映射到Func<Integer, Boolean> ,而不是Scalar<Boolean> Func<Integer, Boolean>以使其接受索引。

这种方法的优点在于所有类和接口都很小,这就是为什么它们很容易组合的原因。 为了限制探针的迭代,我们用Limited装饰它; 为了使它过滤,我们用Filtered装饰它; 为了做其他事情,我们创建一个新的装饰器并使用它。 我们并没有像Stream这样的单一接口。

最重要的是,装饰器是一种用于修改集合行为的面向对象的工具,而流是我什至找不到名称的其他东西。

PS顺便说一下,这就是在Guava的Iterables的帮助下可以实现相同算法的方式:

Iterable<Double> ready = Iterables.limit(Iterables.filter(probes,probe -> probe == 0.0d || probe == 1.0d),10
);
int pos = 0;
for (Double probe : probes) {System.out.printf("Probe #%d: %f", pos++, probe * 100.0d);
}

这是一些面向对象和功能样式的怪异组合。

翻译自: https://www.javacodegeeks.com/2017/10/streams-vs-decorators.html

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

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

相关文章

流线动态图python_Node.js Stream(流)

Node.js Stream(流) Stream 是一个抽象接口&#xff0c;Node 中有很多对象实现了这个接口。例如&#xff0c;对http 服务器发起请求的request 对象就是一个 Stream&#xff0c;还有stdout&#xff08;标准输出&#xff09;。 Node.js&#xff0c;Stream 有四种流类型&#xff1…

gacutil不是内部或外部命令_Win7命令提示符输入taskkill提示不是内部或外部命令...

使用win7系统的用户&#xff0c;想在命令提示符下使用taskkill命令删掉进程的时候&#xff0c;却提示taskkill不是内部或外部命令&#xff0c;也不是可运行的程序&#xff0c;遇到这样的问题&#xff0c;这位用户不知道怎么解决。所以给大家带来了解决方法教程&#xff0c;希望…

mysql两台服务器怎么做数据同步_两台mysql服务器实现双机互备配置并测试数据同步...

对于实现两台机子的互备配置&#xff0c;本文作出了详细的介绍&#xff0c;之后的测试数据同步&#xff0c;在10.168.1.44服务器数据库里修改一条数据&#xff0c; 可以看到数据已经同步过来了。反过来&#xff0c;修改10.168.0.126的数据&#xff0c;也可以看到10.168.1.44数据…

excel 复制数据 sql server 粘贴_win32 实现 excel 快速复制粘贴

直接简明说&#xff1a;该方法可以直接将一张代码的区域内容直接 copy 到另一张表上&#xff0c;并且字体颜色、背景、格式都不变&#xff0c;另外还可以 copy 公式(相当于 excel 下拉公式)from win32com.client import Dispatchimport win32com.clientdef writeCol(filename):…

什么是JAX-RS注释?

JAX-RS概述&#xff08;第1部分&#xff09; JAX-RS API构成Java EE平台承诺提供标准驱动技术的重要组成部分。 互联网无处不在的性质以及对微服务体系结构的日益增长的兴趣已将更多的精力放在小型可扩展的自治服务及其互操作性上。 允许微服务彼此之间以及“外部世界”之间进行…

oracle 查询过去一个星期的数据_过去一星期,最懂我的居然是一个表情包

文/黄亚男编辑/大风微信表情包上新快一周了&#xff0c;除了各个聊天对话框、朋友圈&#xff0c;蔓延到了其它社交平台。小黄脸表情伴随着微信的诞生和升级&#xff0c;迄今在微信上已经四次更新。每一次几乎有一个出圈的表情&#xff1a;第一次是“笑哭”&#xff1b;第二次则…

mysql的count报错_Mysql报错注入原理分析(count()、rand()、group by)

报错需要count(*)&#xff0c;rand()、group by&#xff0c;三者缺一不可前提&#xff1a;当行数大于等于3行时才会报错。原链接&#xff1a;https://www.cnblogs.com/xdans/p/5412468.html几个fool()原理解释&#xff1a;selectcount(*),floor(rand(0)*2) from test group by …

1.0jpa 2.0_EasyCriteria 2.0 – JPA标准应该很容易

1.0jpa 2.0在今天的帖子中&#xff0c;我们将看到名为EasyCriteria的框架的新版本。 在这篇文章的结尾&#xff0c;我们将在博客中看到这里的内容。 不幸的是&#xff0c;JPA标准存在一个巨大的问题&#xff0c;即冗长。 为什么不变得更容易&#xff1f; 像这样认为EasyCriteri…

python 从入门到实践_Python编程从入门到实践日记Day15

Python编程从入门到实践日记Day15第5章 字典(三)1.使用字典(三)—由类似对象组成的字典在前面的示例中&#xff0c;字典存储的是一个对象(游戏中的一个外星人)的多种信息&#xff0c;但你也可以使用字典来存储众多对象的同一种信息。例如&#xff0c;假设你要调查很多人&#x…

mysql创建文章表_创建表--文章表article

建MySQL数据表需要以下信息&#xff1a;表名表字段名定义每个表字段字段名 数据类型 数据属性数据属性:1. 无符号 unsigned(非负限定 ,即不能取负值) 取值范围 0–255&#xff1b;2. 主键索引 primary key(唯一,一张表推荐一个主键) &#xff1b;3. 自增 auto_increment &…

什么是JavaServer Faces(JSF)

这是一个分为两部分的系列&#xff0c;其中我介绍了JSF 2及其如何适合Java EE生态系统。 在第1部分中&#xff0c;我将介绍JavaServer Pages&#xff08;JSF&#xff09;背后的基本思想 &#xff0c;在第2部分中&#xff0c;将介绍Facelets声明语言 。 在构建Web应用程序时&a…

python地图散点图_在地图上叠加散点图(img)

好吧&#xff0c;这个问题是老问题&#xff0c;但我有一个不同的答案&#xff0c;可能会有人感兴趣。。。在 我一直在研究同一个问题。GitHub&#xff08;https://github.com/ageron/handson-ml.git&#xff09;上提供的代码可以满足您的需要&#xff08;请参见02“端到端机器学…

mysql创建表时添加范式_MySql三大范式与数据库设计和表创建常用语句

【数据库设计的三大范式】1.第一范式(1NF First Normal Fromate)&#xff1a;数据表中的每一列(字段)&#xff0c;必须是不可拆分的最小单元。也就是确保每一列的原子性。例如&#xff1a; userInfo: ‘山东省烟台市 13181621008’> userAds:’山东省烟台市’tel:’13181621…

asp listview 单元格文字颜色_如何替换CAD表格中特定区域单元格中的文字?

下面是本公众号文章分类目录&#xff0c;点击标题文字可打开分类文章列表&#xff1a;安装卸载 异常、退出 文件及输入输出 基本操作技巧 各种设置及相关问题 界面和显示相关问题 快捷键 视图设置和调整 图层 颜色 线型 字体、文字样式和文字输入 标注、引线和标注…

jvm 方法内联_方法内联在JVM中有多积极?

jvm 方法内联在IntelliJ IDEA中使用Ctrl Alt M 提取方法 。 Ctrl Alt M。 这就像选择一段代码并按此组合一样简单。 Eclipse也有它 。 我讨厌冗长的方法。 对于我来说&#xff0c;闻起来太久了&#xff1a; public void processOnEndOfDay(Contract c) {if (DateUtils.add…

php ssh 连接mysql_通过PHP中的SSH连接到MySQL服务器?mysql-问答-阿里云开发者社区-阿里云...

SSH隧道解决方案 设置到MySQL数据库服务器的SSH隧道(最好是通过Jumpbox以获得安全性)。(A)GUI工具 根据您的要求&#xff0c;您可以使用具有内置SSH隧道支持的GUI MySQL客户端(例如SequelPro)&#xff0c;使用Visual Studio代码 转发端口/创建SSH隧道或使用PuTTY设置端口转发。…

mybatis delete返回值_面试:谈谈你对MyBatis执行过程之SQL执行过程理解

前言在了解了MyBatis初始化加载过程后&#xff0c;我们也应该研究看看SQL执行过程是怎样执行&#xff1f;这样我们对于Mybatis的整个执行流程都熟悉了&#xff0c;在开发遇到问题也可以很快定位到问题。更重要的&#xff0c;在面试中遇到面试官咨询Mybatis的知识点的时候&#…

GC解释:堆

世代垃圾收集器 JVM堆分为两个不同的世代。 一种称为“年轻”&#xff0c;另一种称为“老”&#xff08;有时称为终身制&#xff09;。 年轻一代又分为两个主要的逻辑部分&#xff1a;伊甸园和幸存者空间。 垃圾收集人员还使用了虚拟空间供年轻人和老年人使用&#xff0c;以调整…

ubuntu设置mysql可以非本地访问_ubuntu server下设置mysql的远程访问权限

安装mysql安装mysql的方式较多主要有使用源安装&#xff0c;使用本地压缩包进行安装的方式。 具体参照 【ubuntu安装mysql5.5】检查mysql的远程访问权限eniZ944qtakg9Z:~$netstat -tl | grep mysql#tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTE…

python调用mysql数据库sql语句过长有问题吗_python操作mysql数据库,一次性执行多条语句不执行...

总结&#xff1a;1、使用这种方法&#xff0c;获取到的返回值总是最后一条命令的返回值&#xff0c;如果最后一条命令是update或者delete这种sql&#xff0c;则返回为&#xff08;&#xff09; 2、sql的每一条语句后面都需要添加一个分号&#xff0c;不然最后splice时候 &#…