java 7.函数-递归_带有谓词的Java中的函数样式-第1部分

java 7.函数-递归

您一直在听到将要席卷全球的函数式编程,而您仍然坚持使用普通Java? 不用担心,因为您已经可以在日常Java中添加一些功能样式。 此外,它很有趣,可以节省许多代码行并减少错误。

什么是谓词?

实际上,当我很早以前在Java 1.4中进行编码时,我第一次发现Apache Commons Collections时就爱上了谓词。 该API中的谓词不过是Java界面,仅包含一种方法:

evaluate(Object object): boolean

就是这样,它只需要一些对象并返回true或false。 带有Apache License 2.0的Google Guava是Apache Commons Collections的更新版本。 它使用通用参数通过一种方法定义了谓词接口:

apply(T input): boolean

就这么简单。 要在应用程序中使用谓词,您只需在自己的单个方法apply(something)中使用您自己的逻辑来实现此接口。  

一个简单的例子

作为早期的示例,假设您有一个PurchaseOrder对象的列表订单 ,每个订单都有一个日期,一个Customer和一个州。 各种用例可能会要求您找出该客户的每个订单,每个待处理,已发货或已交付的订单,或者自上一小时以来完成的每个订单。 当然,您可以通过foreach循环和if内部循环来实现:

//List<PurchaseOrder> orders...public List<PurchaseOrder> listOrdersByCustomer(Customer customer) {final List<PurchaseOrder> selection = new ArrayList<PurchaseOrder>();for (PurchaseOrder order : orders) {if (order.getCustomer().equals(customer)) {selection.add(order);}}return selection;
}

再次针对每种情况:

public List<PurchaseOrder> listRecentOrders(Date fromDate) {final List<PurchaseOrder> selection = new ArrayList<PurchaseOrder>();for (PurchaseOrder order : orders) {if (order.getDate().after(fromDate)) {selection.add(order);}}return selection;
}

重复非常明显:除了if子句中的条件(此处以黑体强调)之外,每个方法都是相同的。 使用谓词的想法只是通过调用谓词来代替if子句中的硬编码条件,然后调用谓词。 这意味着您只能编写一个方法,将谓词作为参数,并且仍然可以覆盖所有用例,甚至已经支持了您尚不知道的用例:

public List<PurchaseOrder> listOrders(Predicate<PurchaseOrder> condition ) {final List<PurchaseOrder> selection = new ArrayList<PurchaseOrder>();for (PurchaseOrder order : orders) {if (condition.apply(order)) {selection.add(order);}}return selection;
}

每个谓词可以在多个地方使用时定义为独立类,也可以定义为匿名类:

final Customer customer = new Customer("BruceWaineCorp");
final Predicate<PurchaseOrder> condition = new Predicate<PurchaseOrder>() {public boolean apply(PurchaseOrder order) {return order.getCustomer().equals(customer);}
};

使用真正的函数式编程语言(Scala,Clojure,Haskell等)的朋友会评论说,上面的代码非常冗长,无法完成某些非常常见的事情,我必须同意。 但是,我们已经习惯了Java语法中的冗长性,并且我们拥有功能强大的工具(自动完成,重构)来适应它。 而且我们的项目可能无法在一夜之间切换到另一种语法。  

谓词是收藏最好的朋友

回到我们的示例,我们只编写了一次foreach循环来覆盖每个用例,我们对此表示满意。 但是,您的朋友“真正地”进行函数式编程仍然可以嘲笑您必须自己编写的循环。 幸运的是,来自Apache或Google的API也都提供了您可能期望的所有优点,特别是类似于java.util.Collections的类,因此命名为Collections2 (不是一个非常原始的名称)。

此类提供了一个方法filter() ,它的功能类似于我们之前编写的内容,因此我们现在可以完全不使用循环来重写方法:

public Collection<PurchaseOrder> selectOrders(Predicate<PurchaseOrder> condition) {return Collections2.filter(orders, condition);
}

实际上,此方法返回一个筛选视图:

返回的集合是unfiltered的实时视图(输入集合); 改变一个会影响另一个。

这也意味着更少的内存使用,因为是从未经过滤的 过滤 ,以实际返回的集合初始收集没有实际的副本。

在类似的方法上,给定一个迭代器,您可以在它之上请求一个经过过滤的迭代器(Decorator模式),该迭代器仅为您提供谓词选择的元素:

Iterator filteredIterator = Iterators.filter(unfilteredIterator, condition);

由于Java 5的Iterable接口在foreach循环中非常方便使用,因此我们更愿意使用以下表达式:

public Iterable<PurchaseOrder> selectOrders(Predicate<PurchaseOrder> condition) {return Iterables.filter(orders, condition);
}// you can directly use it in a foreach loop, and it reads well:
for (PurchaseOrder order : orders.selectOrders(condition)) {//...
}

现成的谓词

要使用谓词,您可以简单地定义自己的接口谓词,或者为应用程序中需要的每个类型参数定义一个。 这是可能的,但是使用来自诸如Guava或Commons Collections之类的API的标准谓词接口的好处是,API带来了许多出色的构建块,可与您自己的谓词实现结合使用。

首先,您甚至根本不需要实现自己的谓词。 如果您所需要的只是一个对象是否等于另一个条件或不为空的条件,那么您可以简单地要求谓词:

// gives you a predicate that checks if an integer is zero
Predicate<Integer> isZero = Predicates.equalTo(0);
// gives a predicate that checks for non null objects
Predicate<String> isNotNull = Predicates.notNull();
// gives a predicate that checks for objects that are instanceof the given Class
Predicate<Object> isString = Predicates.instanceOf(String.class);

给定一个谓词,您可以将其求逆(true变为false,反之亦然):

Predicates.not(predicate);

使用布尔运算符AND或OR组合多个谓词:

Predicates.and(predicate1, predicate2);
Predicates.or(predicate1, predicate2);
// gives you a predicate that checks for either zero or null
Predicate<Integer> isNullOrZero = Predicates.or(isZero, Predicates.isNull());

当然,您还具有总是返回true或false的特殊谓词,它们确实非常有用,我们将在以后的测试中看到:

Predicates.alwaysTrue();
Predicates.alwaysFalse();

谓词在哪里

我经常经常一开始会做匿名谓词,但是它们总是经常被使用,因此经常被提升为实际的类,无论是否嵌套。

顺便说一下,这些谓词在哪里定位? 遵循罗伯特·马丁( Robert C. Martin) 及其共同封闭原则(CCP) :

一起变化的类,一起属于

因为谓词操纵某种类型的对象,所以我喜欢将它们共置为靠近它们作为参数的类型。 例如, CustomerOrderPredicatePendingOrderPredicateRecentOrderPredicate类应与它们评估的PurchaseOrder类驻留在同一包中,或者如果它们很多,则位于子包中。 另一个选择是将它们嵌套在类型本身内。 显然,谓词与它们所操作的对象非常相关。

资源资源

以下是本文示例的源文件: cyriux_predicates_part1 (zip)

在下一部分中 ,我们将了解谓词如何简化测试,它们如何与域驱动设计中的规范相关联,以及一些其他方面的知识,以使您的谓词发挥最大作用。

参考: 带有谓词的纯Java语言中的函数式风格– Cyrille Martraire博客博客中JCG合作伙伴 Cyrille Martraire的第1部分 。


翻译自: https://www.javacodegeeks.com/2012/05/functional-style-in-java-with.html

java 7.函数-递归

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

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

相关文章

大话oraclerac集群、高可用性、备份与恢复_数腾Oracle RAC数据库灾备解决方案

“一个系统包含很多模块&#xff0c;数据库、前端、缓存、搜索、消息队列等&#xff0c;每个模块都需要做到高可用&#xff0c;才能保证整个系统的高可用。”数据库作为现代信息社会的基石&#xff0c;几乎所有的计算机应用软件都构建于数据库系统之上&#xff0c;对于数据库而…

Android面试题Service,Android面试题-IntentService源码分析

自定义控件联网工具数据库源码分析相关面试题Activity相关面试题Service相关面试题与XMPP相关面试题与性能优化相关面试题与登录相关面试题与开发相关面试题与人事相关面试题人事面试宝典IntentService是继承于Service并处理异步请求的一个类&#xff0c;在IntentService内有一…

OpenGL中的Shader

http://blog.csdn.net/huangcanjun187/article/details/52474365 学习总结自&#xff1a;http://learnopengl.com/#!Getting-started/Hello-Triangle http://learnopengl.com/#!Getting-started/Shaders 继上篇文章中提到&#xff0c;OpenGL是为了在GPU上同时跑成千上万个程序&…

在html中金色怎么写,ps金色数值是多少?

一些常用的金色表示值&#xff1a;R255&#xff0c;G215&#xff0c;B0R205&#xff0c;G127&#xff0c;B50R166&#xff0c;G124&#xff0c;B64R217&#xff0c;G217&#xff0c;B25关于金色rgb值&#xff0c;金色就是黄色&#xff0c;但是我们看到的一些金色效果只是用颜色…

EAP 7 Alpha和Java EE 7入门

红帽JBoss企业应用程序平台7&#xff08;JBoss EAP 7&#xff09;是基于开放标准构建并符合Java Enterprise Edition 7规范的中间件平台。 它基于WildFly等经过验证的创新开源技术之上&#xff0c;它将使Java EE 7的开发变得更加容易。 这是有关如何开始使用最新ALPHA版本的快速…

简单点赞效果html,js实现点赞效果

javascript实现点赞或踩加一&#xff0c;再点一次减一的效果好多新手在网上找不到点赞效果的代码&#xff0c;今天给大家分享一个采用js写的简单方法(有点错误&#xff0c;已修正)效果图如下HTML代码可直接ctrl c复制代码3030CSS代码可直接ctrl c复制代码(注&#xff1a;样式…

html显示和隐藏不占空间的是什么,css怎么设置不占用空间的隐藏?

css怎么设置不占用空间的隐藏&#xff1f;下面本篇文章就来给大家介绍一下使用CSS设置不占用空间隐藏的方法。有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对大家有所帮助。在CSS中&#xff0c;可以利用display属性&#xff0c;设置display:none来设…

javame_JavaME:Google静态地图API

javame无论您是需要基于位置的应用程序的地图还是只是出于娱乐目的&#xff0c;都可以使用有史以来最简单的方法&#xff1a;Google Static Maps API。 在这篇文章中&#xff0c;我们将看到如何从纬度和经度获得地图作为图像。 可以使用Location API获得纬度和经度&#xff0c;…

js如何获取html图片,JS/JQuery获取网页或文章或某DIV所有图片

要获取网页所有图片&#xff0c;我们可以通过Javascript就能轻松实现&#xff0c;不过要想获得文章或某容器(如&#xff1a;Div)里所有图片&#xff0c;使用JQuery而不是Javascript来实现就会变得更加简单。本文将给你详细介绍。通过Javascript获取网页所有图片html代码JS/JQue…

带有Netflix Ribbon的Spring Cloud Rest Client-基础知识

在较早的博客文章中&#xff0c;我介绍了Spring Cloud世界中REST客户端的各种选项。 所有选项围绕着基于Netflix OSS的名为Ribbon的组件&#xff0c;该组件处理与承载服务的不同实例之间的调用负载平衡&#xff0c;处理故障转移&#xff0c;超时等有关的方面。在此&#xff0c;…

html中给文章怎么设置行高,css如何设置行距?

在网页的布局中几大段文字挤在一起总归是不好看的&#xff0c;这时候我们就需要来设置行间距来让文字看起来不拥挤&#xff0c;也让整个页面看起来美观整洁&#xff0c;那么&#xff0c;行间距该如何设置呢&#xff1f;本篇文章就来给大家介绍一下css行间距的设置方法。首先我们…

初中数学知识点总结_初中物理 | 最全知识点总结

往期回顾初中物理 | 知识点总结一&#xff1a;机械运动初中物理 | 知识点总结二&#xff1a;声现象初中物理 | 知识点总结三&#xff1a;物态变化初中物理 | 知识点总结四&#xff1a;光现象初中物理 | 知识点总结五&#xff1a;透镜及其应用初中物理 | 知识点总结六&#xff1…

redis版本_全球首发|阿里云正式推出云数据库Redis6.0版本

Redis 6.0更多精彩详情2020年6月23日&#xff0c;阿里云正式推出云数据库Redis 6.0版本。Redis 6.0版本为Redis开源社区于5月2日发布的全新版本&#xff0c;包含多项重大功能更新和大幅度的性能提升。依托于阿里云强大的云服务与管控能力&#xff0c;以及团队的快速跟进&#x…

webclient无法获取html文件,C# WebClient获取网页源码的方法

效果如图完整代码如下using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;//引入以下命名空间using System.Net;using System.IO;using System.Threading;name…

基于javafx的五子棋_基于JavaFX的SimpleDateFormat演示程序

基于javafx的五子棋对于使用Java Date进行格式化的新手&#xff0c;甚至对于使用Java Date进行格式化的新手&#xff0c;对于有经验的Java开发人员来说&#xff0c;可能都会有些棘手&#xff0c;其中之一就是使用SimpleDateFormat指定日期/时间格式。 SimpleDateFormat的基于类…

监督分类空白处也被分类了_监督学习(2)|本质是分类的“逻辑回归”

引言机器学习&#xff0c;绕不开预测问题&#xff0c;预测绕不开回归和分类。本篇介绍最常用的二分类算法&#xff1a;逻辑回归(Logistics Regression)&#xff0c;当然随着算法的发展&#xff0c;它也可用于多分类问题。每一个算法都是许许多多数学家的努力铸就&#xff0c;理…

html网页制作图案,巧用CSS滤镜做图案文字-网页设计,HTML/CSS

请先看看以下演示中的图案文字。这可不是图片效果&#xff0c;而是用css滤镜中的chroma() 语句做成的文本文字&#xff0c;其中文本的内容和图案都可以自由设定。先介绍一下这个神奇的滤镜&#xff1a;chroma() 滤镜。语法&#xff1a; filter:chroma( color#cccccc) &#xff…

JavaOne 2015 –又一年,又向前迈进了一步

JavaOne 2015旧金山于10月25日至29日举行。 我很自豪地说这是我第九个人参加JavaOne&#xff0c;第七个人是演讲者&#xff0c;第四个人是Oracle员工&#xff0c;第三个人是内容委员会的成员&#xff0c;第二个人是项目负责人。 我认为对于JavaOne来说&#xff0c;这是又一个美…

html div父集子集,抛砖引玉css系列---根据父元素包含的子元素个数,实现不同的样式...

工作时遇到这样一个问题:根据某元素所包含的子元素个数&#xff0c;分别设置不同的样式&#xff0c;这个用js可以解决&#xff0c;不过个人认为用css解决可能更简单一点。这也正好加深了我对css选择器的理解和运用。demo如下&#xff1a;效果图如下完整代码如下&#xff1a;css…

rnn按时间展开_双向RNN的理解

我们在学习某种神经网络模型时&#xff0c;一定要把如下几点理解透了&#xff0c;才算真正理解了这种神经网络。网络的架构&#xff1a;包含那些层&#xff0c;每层的输入和输出&#xff0c;有那些模型参数是待优化的前向传播算法损失函数的定义后向传播算法什么情况下认为是发…