fold函数_Java中使用Map and Fold进行函数式编程

fold函数

在函数式编程中,Map和Fold是两个非常有用的运算符,它们属于每种函数式语言。 如果Map和Fold运算符是如此强大且必不可少,那么您如何解释说即使Java编程语言缺少这两个运算符,我们也可以使用Java来完成工作? 事实是,使用Java进行编码时,您已经进行了Map和Fold,只是每次都使用循环手动进行操作。

免责声明:我不是函数式编程的参考,本文不过是一个简短的介绍。 FP爱好者可能不太喜欢它。

您已经熟悉了

想象一下不含增值税的数量的List <Double>。 我们希望将此列表转换为包含增值税的另一个相应列表。 首先,我们定义一种将增值税加到一个单一金额中的方法:

public double addVAT(double amount, double rate) {return amount * (1 + rate);}

现在让我们将此方法应用于列表中的每个金额:

public List<Double> addVAT(List<Double> amounts, double rate){final List<Double> amountsWithVAT = new ArrayList<Double>();for(double amount : amounts){amountsWithVAT.add(addVAT(amount, rate));}return amountsWithVAT;
}

在这里,我们创建了另一个输出列表,对于输入列表的每个元素,我们对其应用addVAT()方法,然后将结果存储到大小完全相同的输出列表中。 恭喜,正如我们刚刚手工完成的,在方法addVAT()的输入列表上有一个Map。 让我们再做一次。

现在我们要使用货币汇率将每个金额转换为另一种货币,因此我们需要一种新的方法:

public double convertCurrency(double

public double convertCurrency(double amount, double currencyRate){return amount / currencyRate;}

现在,我们可以将此方法应用于列表中的每个元素:

public List<Double> convertCurrency(List<Double> amounts, double currencyRate){final List<Double> amountsInCurrency = new ArrayList<Double>();for(double amount : amounts){amountsInCurrency.add(convertCurrency(amount, currencyRate));}return amountsInCurrency;
}

注意,除了在步骤2处调用的方法外,两种接受列表的方法是如何相似的:

  1. 创建一个输出列表,
  2. 为输入列表中的每个元素调用给定方法 ,并将结果存储到输出列表中
  3. 返回输出列表。

您经常在Java中执行此操作,而这恰恰是Map运算符:将给定方法someMethod (T):T应用于list <T>的每个元素,这将为您提供另一个相同大小的list <T>。

功能语言认识到这种特殊需求(在集合的每个元素上应用一种方法)非常普遍,因此他们将其直接封装到内置的Map运算符中。 这样,给定addVAT(double,double)方法,我们可以使用Map运算符直接编写如下代码:

List amountsWithVAT = map (addVAT, amounts, rate)

是的,第一个参数是函数,因为函数是函数语言中的一等公民,因此可以将它们作为参数传递。 与for循环相比,使用Map运算符更简洁,更不易出错,其意图也更加明确,但是我们在Java中没有它……

因此,这些示例的要点在于,您已经不熟悉甚至不知道函数式编程的关键概念:Map运算符。

现在是Fold运算符

回到金额列表,现在我们需要将总金额计算为每个金额的总和。 超级容易,让我们循环执行一下:

public double totalAmount(List<Double> amounts){double sum = 0;for(double amount : amounts){sum += amount;}return sum;
}

基本上,我们只是在列表上进行了折叠,使用函数“ + =”将每个元素折叠为一个元素,这里是一个数字,一次递增地折叠。 这类似于Map运算符,除了结果不是列表而是单个元素(标量)。

这又是您通常用Java编写的那种代码,现在您已经用功能语言为它命名:“ Fold ”或“ Reduce”。 Fold运算符通常在函数式语言中是递归的,因此在此不再对其进行描述。 但是,我们可以使用某种可变状态在迭代之间累加结果,从而以迭代形式实现相同的目的。 在这种方法中,Fold采用一种内部可变状态的方法,该方法期望一个元素,例如someMethod(T),并将其重复应用于输入列表<T>中的每个元素,直到我们得到一个单个元素T,即折叠操作的结果。

与Fold一起使用的典型函数是求和,逻辑与与或,List.add()或List.addAll(),StringBuilder.append(),max或min等。Fold的思维方式类似于SQL中的聚合函数 。

形状思考

直观地思考(带有草率的图片),Map接收一个大小为n的列表,并返回另一个大小相同的列表:

另一方面,Fold获取大小为n的列表,并返回单个元素(标量):

您可能还记得我之前关于谓词的文章 ,这些文章通常用于将集合过滤为元素较少的集合。 实际上,此过滤器运算符是在大多数功能语言中补充Map和Fold的第三种标准运算符。

Eclipse模板

由于Map和Fold很常见,因此有必要为它们创建Eclipse模板,例如Map:

在Java中更接近地图和折叠

Map和Fold是期望函数作为参数的构造,而在Java中,传递方法的唯一方法是将其包装到接口中。

在Apache Commons Collections中,有两个接口对于我们的需求特别有趣: Transformer (具有一个方法transform(T):T )和Closure (具有一个方法execute(T):void) 。 类CollectionUtils提供了方法collect(Iterator,Transformer) ,它基本上是Java集合的穷人Map运算符,以及提供了可以使用闭包来模拟Fold运算符的forAllDo()方法。

使用Google Guava, Iterables类提供了静态方法transform(Iterable,Function) ,该方法基本上是Map运算符。

List<Double> exVat = Arrays.asList(new Double[] { 99., 127., 35. });Iterable<Double> incVat = Iterables.transform(exVat, new Function<Double, Double>() {public Double apply(Double exVat) {return exVat * (1.196);}});System.out.println(incVat); //print [118.404, 151.892, 41.86]

类似的变换()方法,也可在类解释为解释和地图为地图。

要在Java中模拟Fold运算符,可以使用Closure接口,例如Apache Commons Collection中的Closure接口,仅使用一个带有一个参数的单一方法,因此必须在内部保留当前的-mutable-状态,就像'+ =确实。

不幸的是,Guava中没有Fold,尽管它经常被要求提供 ,甚至没有类似闭包的函数,但是创建自己的函数并不难,例如,您可以使用以下方式实现上述总计:

// the closure interface with same input/output type
public interface Closure<T> {T execute(T value);
}// an example of a concrete closure
public class SummingClosure implements Closure<Double> {private double sum = 0;public Double execute(Double amount) {sum += amount; // apply '+=' operatorreturn sum; // return current accumulated value}
}// the poor man Fold operator
public final static <T> T foreach(Iterable<T> list, Closure<T> closure) {T result = null;for (T t : list) {result = closure.execute(t);}return result;
}@Test // example of use
public void testFold() throws Exception {SummingClosure closure = new SummingClosure();List<Double> exVat = Arrays.asList(new Double[] { 99., 127., 35. });Double result = foreach(exVat, closure);System.out.println(result); // print 261.0
}

不仅用于收藏:可折叠在树木和其他建筑物上

Map and Fold的功能不仅限于简单的集合,还可以扩展到任何可导航的结构,尤其是树和图。

想象一棵使用带有其子节点的类Node的树。 最好将深度优先搜索和广度优先搜索(DFS和BFS)编码成两个接受Closure作为单个参数的通用方法:

public class Node ...{...public void dfs(Closure closure){...}public void bfs(Closure closure){...}
}

过去,我经常使用这种技术,我可以说它可以大大减少类的大小,仅使用一种通用方法,而不是许多看起来相似的方法(每个方法都会重做自己的树遍历)。 更重要的是,可以使用模拟闭包对遍历本身进行单元测试。 每个封盖也可以独立进行单元测试,所有这些都使您的生活变得更加简单。

访客模式可以实现非常相似的想法,您可能已经很熟悉。 我在代码和其他几个团队的代码中多次看到,Visitor非常适合在遍历数据结构期间累积状态。 在这种情况下,Visitor只是闭合中传递给折叠的一种特殊情况。

Map-Reduce上的一个字

您可能听说过Map-Reduce模式,是的,其中的“ Map”和“ Reduce”一词指的是我们刚刚看到的相同的函数运算符Map和Fold(也称为Reduce)。 尽管实际应用更加复杂,但很容易注意到Map 令人尴尬地是并行的,这对并行计算有很大帮助。

参考:来自我们的JCG合作伙伴的 日常Java中的Map和Fold功能编程思考   Cyrille Martraire 博客上的Cyrille Martraire 。


翻译自: https://www.javacodegeeks.com/2012/03/functional-programming-with-map-and.html

fold函数

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

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

相关文章

NVIC优先级分组

挂起&#xff0c;解挂&#xff0c;使能&#xff0c;失能 转载于:https://www.cnblogs.com/alantechnique/p/5598374.html

【Egret】Wing3发布移动APP功能,打包APK流程以及会遇到的问题

流程&#xff1a;1.安装好wing 3&#xff0c;然后 插件——Egret项目工具——发布移动APP——Build android native project 2.配置发布环境&#xff1a; Android 1.egret engine 点击下载2.android sdk mac版下载 windows版下载3.java sdk mac版下载 windows版…

有效运维的 on-call 机制

[编者按]本文作者为云告警平台OneAlert负责人&#xff0c;著《云计算与OpenStack》&#xff0c;在IT运营管理、云计算方面从业10多年。 正文 互联网技术的发展&#xff0c;离不开运维支撑工作&#xff0c;没有零bug的程序&#xff0c;没有不出问题的系统&#xff0c;问题故障不…

团队项目:界面设计

游戏内关卡为2D横版界面&#xff0c;背景为楼群贴图&#xff0c;整体色调以灰色为主&#xff0c;与摩托车手的主题相配。游戏中配有音效及背景音乐&#xff0c;背景音乐为我组成员自行创作录制完成。界面展示如下&#xff1a; 图1 游戏中设计图 图中显示的摩托车手即为玩家操控…

Hystrix简介

在过去的几天里&#xff0c;我一直在探索Netflix Hystrix库&#xff0c;并欣赏了这个出色的库所提供的功能。 引用Hystrix网站上的内容&#xff1a; Hystrix是一个延迟和容错库&#xff0c;旨在隔离对远程系统&#xff0c;服务和第三方库的访问点&#xff0c;停止级联故障&am…

MP3音乐播放器搜索引擎-鼠标拖动窗口

定义鼠标的按压&#xff0c;移动&#xff0c;施放事件 &#xff08;1&#xff09;鼠标的按压事件 globalpos是全局坐标&#xff0c;即鼠标相对于桌面屏幕左上角的坐标我们通过this->frameGeometry().topLeft();可以获得当前窗口的左上角的x左边或y坐标 在移动事件中我们可以…

SpringMVC学习--文件上传

简介文件上传是web开发中常见的需求之一&#xff0c;springMVC将文件上传进行了集成&#xff0c;可以方便快捷的进行开发。 springmvc中对多部件类型解析在 页面form中提交enctype"multipart/form-data"的数据时&#xff0c;需要springmvc对multipart类型的数据进行解…

VS code常用的快捷键

在前端的开发过程中&#xff0c;如果有一个比较好的开发工具&#xff0c;配合一些常用的快捷键&#xff0c;开发效率将大大提升&#xff0c;正所谓工具善其事必先利其器。前端推荐使用编辑器VS code,用过HB-X&#xff0c;ST3,Webstorm等编译器之后就会发现&#xff0c;前端编辑…

平台日志架构说明log4j漏洞问题解析

Log4j是Apache的一个开源项目&#xff0c;通过使用Log4j&#xff0c;我们可以控制日志信息输送的目的地是控制台、文件、GUI组件&#xff0c;甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等&#xff1b;我们也可以控制每一条日志的输出格式&#xff1b;通过定义每…

2016/06/22 中色启动筹码分析作业

2016/06/22 中色启动筹码分析作业——待核实 201转载于:https://www.cnblogs.com/carl2380/p/5608596.html

浏览器各个属性的作用

作为前端程序员不可避免的会和浏览器打交道&#xff0c;所以要对浏览器的各个属性的作用进行了解&#xff0c;方便开发及调试&#xff0c;这里以谷歌浏览器为例进行简单的介绍。一是巩固对浏览器属性的认识&#xff0c;二是方便大家的学习。首先打开谷歌浏览器按F12查看控制台属…

Moment.js日期处理库的使用

Moment.jsMoment.js是一个轻量级的JavaScript时间库&#xff0c;它方便了日常开发中对时间的操作&#xff0c;提高了开发效率。这个在一些金融保险公司会经常用到&#xff0c;比如一下时间的格式化处理&#xff0c;时间的选择等等。这个比较好的地方是可以格式化时间&#xff0…

转: 微博的多机房部署的实践(from infoq)

转: http://www.infoq.com/cn/articles/weibo-multi-idc-architecture 在国内网络环境下&#xff0c;单机房的可靠性无法满足大型互联网服务的要求&#xff0c;如机房掉电&#xff0c;光缆被挖的情况也发生过。微信就曾发生大面积故障&#xff0c;包括微信信息无法发出、无法刷…

知道这些性能优化手段,工资起码提升一倍

1.什么是性能?性能指标有哪些&#xff1f;计算机的性能&#xff0c;其实和我们干体力劳动很像&#xff0c;好比是我们要搬东西。对于计算机的性能&#xff0c;我们需要有个标准来衡量。这个标准中主要有两个指标。第一个是响应时间&#xff08;Response time&#xff09;或者叫…

亲手把360奇安信软件卸载了,爽!

由于工作原因&#xff0c;在上一家公司安装了360奇安信安全软件&#xff0c;到了下一个公司还需要安装另一个安全软件&#xff0c;这个必须要卸载&#xff0c;卸载&#xff01;卸载&#xff01;但是卸载需要输入密码&#xff0c;没有密码还输入卸载不了&#xff0c;我曾经联系3…

VM虚拟机中CentOS6.4操作系统安装一

在 VMware中鼠标单击“编辑虚拟机设置”&#xff0c;在弹出的“虚拟机设置”对话框中的“硬件”标签中选择“CD/DVD&#xff08;IDE&#xff09;”&#xff0c;然后在右侧的“CD /DVD&#xff08;IDE&#xff09;”连接选项中选择“使用ISO映像文件”&#xff0c;使用“浏览”按…

vue基础教程总结篇,用最短的时间入门vue.js(持续更新...)

目前&#xff0c;vue已经成为前端工程师必会的框架之一&#xff0c;这里简单总结一下&#xff0c;可以让您快速的入门vue,师傅带进门&#xff0c;修行靠个人&#xff0c;最主要的还是自己多动手&#xff0c;多实践&#xff0c;本专栏会持续更新。 1.vue安装教程及简介 2.vue计…

关于SP一些响应码的API返回码及解析集合

在一些金融的行业&#xff08;银行、证券、保险等&#xff09;&#xff0c;如果接触了一些中间件&#xff0c;比如长城、恒银、广电等一些厂商的设备&#xff0c;不同的厂商有不同的一些规范&#xff0c;在应用开发的过程中难免会和中间件的错误码打交道&#xff0c;这里总结一…

eclipselink_Java EE 7的高峰– EclipseLink的多租户示例

eclipselink水族馆是有关所有相关规范和参考实现中有关Java EE进度的灵感和最新信息的重要来源。 他们从Oracle的Shaun Smith&#xff08; 博客 / 推特 &#xff09;获取了有关EclipseLink作为开源项目的地位和未来的演讲。 他介绍了将在EclipseLink 2.4中提供的所有新功能&…

关于一些常见智柜问题的分析及解决办法

竟然还有小伙伴感觉自研项目不好的小伙伴&#xff1f;渐渐感觉不管是在小公司或者在大公司&#xff0c;能有一个值得奋斗的远方就可以了&#xff0c;比如薪资高&#xff0c;钱多事少离家近&#xff0c;自己真的对自己目前做的事情感兴趣&#xff0c;否则干啥都感觉没劲&#xf…