热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java函数式编程_最后用Java进行函数式编程

java函数式编程在许多文章中,我们探讨了针对不同语言的函数式编程概念,其中F#和Scala是对话的重点。但是,由于我在工作

java 函数式编程

在许多文章中,我们探讨了针对不同语言的函数式编程概念,其中F#Scala是对话的重点。 但是,由于我在工作场所进行过Java编程,因此探索这些相同的概念似乎很有趣并且令人大开眼界,因为自从我上次认真使用Java以来已有很长时间了。

高阶函数

如此处所述, 高阶函数是什么? 高阶函数是简单函数,可以将函数作为参数接收,并可以将另一个函数作为结果返回。

在现代Java中 ,我们可以轻松地做到这一点。 语法不是最好的,并且因为没有类型推断,我们必须显式声明函数类型,这在Java中意味着某种接口 。 让我们看看如何。

首先,假设我们有一个对象集合,也就是狗的集合,并且我们有一个作用于每只狗的函数。 我们希望能够在每个对象(狗)上调用此函数。

让我们看看如何创建这样的函数。

@FunctionalInterface
interface DogAge {
Integer apply ( Dog dog ) ;
}

List < Integer > getAges ( List < Dog > dogs, DogAge f ) {

List < Integer > ages &#61; new ArrayList <>() ;

for ( Dog dog : dogs ) {
ages.add ( f.apply ( dog )) ;
}

return ages;
}

我们定义一个给定狗的接口&#xff0c;它从中提取一些Integer值。 然后&#xff0c;我们定义一个函数getAges &#xff0c;该函数将传递的函数&#xff08;现在为接口 &#xff09;应用于每条狗。

现在&#xff0c;我们必须创建要应用于每只狗的实际功能。

DogAge f &#61; dog -> dog.getAge () ;

getAges( dogs, f ) ;

注意&#xff0c;我们不必像在旧版Java中那样实际定义DogAge实现。 这将是以下方式&#xff0c;但是请不要再使用它了。

DogAge dontUseMe &#61; new DogAge () {
&#64;Override
public Integer apply ( Dog dog ) {
return dog.getAge () ;
}
}
;

前者实际上是由编译器在看到第一个时生成的。

我们可以更进一步&#xff0c;并执行以下操作。

getAges( dogs, dog -> dog.getAge ()) ;

在这里&#xff0c;我们将函数直接传递给getAges方法。

不知何故&#xff0c; getAges是一个高阶函数&#xff0c;因为它可以接收函数作为参数。 Java通过接收接口来使签名保持怪异&#xff0c;但是我想这会在该语言的将来版本中得到改善。

为了有一个比较点&#xff0c;让我们在Scala中定义getAges并查看差异。 另外&#xff0c;我们将立即更改函数名称&#xff0c;以便更通用。

def extractStringFromDogs(dogs: List[Dog], f: Dog &#61;> String) &#61;
dogs.map(f)

Java中 &#xff0c;我们可以做到。

&#64;FunctionalInterface
interface DogMapper {
String apply ( Dog dog ) ;
}

List extractStringFromDogs(List dogs, DogMapper f) {

return dogs.stream().map(dog -> f.apply(dog)).collect(Collectors.toList);
}

碰巧Java中已经有一个结构可以解决这个问题。 那就是Function 。 换句话说&#xff0c;我们可以做到。

List extractStringFromDogs(List dogs, Function f) {

return dogs.stream().map(dog -> f.apply(dog)).collect(Collectors.toList);
}

extractStringFromDogs(dogs, dog -> dog.getName());

现在&#xff0c;如何定义实际上返回其他函数的函数呢&#xff1f;

Scala中 &#xff0c;我们可以执行以下操作。

scala> def sum(): (Int, Int) &#61;> Int &#61; (a, b) &#61;> a &#43; b
sum : ()(Int, Int) &#61;> Int

scala> sum()
res1 : (Int, Int) &#61;> Int &#61; $$Lambda$1067/2036949810&#64;715f45c6

scala> sum()(4,5)
res2 : Int &#61; 9

scala> res1(2, 3)
res3 : Int &#61; 5

在这里&#xff0c; sum返回一个可以在其他时间存储和评估的函数。 这是功能语言的非常强大且重要的构造。 我们可以在Java中做同样的事情吗&#xff1f;

让我们首先为这个特定问题定义我们自己的函数类型&#xff08; Functional Interface &#xff09;。

&#64;FunctionalInterface
interface TakeTwo {
Integer apply ( Integer a, Integer b ) ;
}

如我们所见&#xff0c; TakeTwo在语义上与我们在Scala中定义的相同。

现在&#xff0c;我们可以再次定义sum方法。

TakeTwo sum () {
return ( a, b ) -> a &#43; b;
}

TakeTwo mySum &#61; sum() ;

Integer finalSum &#61; mySum.apply ( 5, 6 ) ;

这与我们在Scala中所做的完全相同&#xff0c;只是在Scala中 &#xff0c;语法简洁明了&#xff0c;无需定义将函数接口用作函数类型。 是的&#xff0c;可以达到相同的结果。

再一次&#xff0c;我们实际上不必自己定义TakeTwo &#xff0c;因为在Java中已经定义了一个等效的接口BiFunction 。 通过使用它&#xff0c;我们可以通过以下方式写

BiFunction < Integer, Integer, Integer > sum () {
return ( a, b ) -> a &#43; b;
}

更多功能接口。

为了支持函数式编程&#xff0c; Java集成了许多这些函数式接口 。 他们之中有一些是&#xff1a;

消费者

Java&#xff1a;

public interface Consumer < T > {
void accept ( T t ) ;
....
}

斯卡拉

T &#61;> Unit

谓词

Java

public interface Predicate < T > {
boolean test ( T t ) ;
...
}

斯卡拉

T &#61;> boolean

供应商

Java

public interface Supplier < T > {
T get () ;
}

斯卡拉

:&#61;> T

功能

Java

public interface Function < T, R > {
R apply ( T t ) ;
...
}

斯卡拉

T &#61;> R

双功能

Java

public interface BiFunction < T, U, R > {
R apply ( T t, U u ) ;
...
}

斯卡拉

(T, U) &#61;> R

这些只是新Java及其在Scala中的对等功能&#xff08; 功能接口 &#xff09;中的几种。 注意&#xff0c;在Scala中&#xff0c;我们不必为其定义任何接口&#xff0c;只需在其中具有函数即可&#xff0c;我们可以根据需要定义它们。

结论

Java肯定会以某种方式向函数式编程迈进&#xff0c;即使语法不是最方便的一种&#xff0c;其结果也是相同的。

另一方面&#xff0c; Scala语法要精确得多&#xff0c;并且可以更好地显示意图&#xff0c;而无需将接口创建为函数类型。

我只是希望Java继续发展&#xff0c;同时减少冗长程度并添加新的功能构造&#xff0c;因为最终&#xff0c;我们&#xff08;工程师&#xff09;才是从中获得真正好处的人。

翻译自: https://hackernoon.com/finally-functional-programming-in-java-ad4d388fb92e

java 函数式编程



推荐阅读
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
author-avatar
幸福的肖巍
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有