java 柯里化_函数式编程(Java描述)——Java中的函数及其柯里化

 2023-09-16 阅读 26 评论 0

摘要:本文继续上一篇的内容在Java中,函数可以表现为一个普通的方法、一个lambda表达式,又或者方法引用,甚至是匿名类。本文不会介绍匿名类这种形式。方法Java中的方法,Java使用方法这一概念来表示我们称之为函数的东西。一个方法是函数式的,只要

本文继续上一篇的内容1182b5c498a00cb4d71a7ace3eb1b573.png

在Java中,函数可以表现为一个普通的方法、一个lambda表达式,又或者方法引用,甚至是匿名类。本文不会介绍匿名类这种形式。

方法

Java中的方法,Java使用方法这一概念来表示我们称之为函数的东西。一个方法是函数式的,只要它满足纯函数的额要求(注:上一章有详细介绍)。但是在Java中,一个方法不可能被当成参数传递给另一个方法,你也就无法复合这些方法。Java的方法只属于它在的类。

函数的复合:

java函数式编程的好处、就和高中数学所学的那样,程序里的函数也可以相互复合。这里有两个函数:

f (x) = x+1;

g(x) = x*2;

函数f和g复合后即为f(g(x)) = f(x*2)=(x*2)+1;我们可以为新函数起个名,即h(x)= (x*2)+1;

将参数3应用于这个复合函数可得 f(g(3)) =6+1  =7;

JAVA函数式编程?所幸的是,Java为我们提供了函数式接口和lambda表达式来模拟这一过程。使用我们上一章定义的Function接口,我们可以表示上面的例子:

Function f = i -> i + 1;

Function g = i -> i * 2;

Function h = f.compose(g);

int result = h.apply(3); //“7”

java构造函数初始化、我们也可以使用andThen方法,f.andThen(g)代表的含义是将f函数得到的结果作为参数应用到函数g。

这两个方法定义如下:

public interface Function {

U apply(T t);

default Function compose(Function f) {

java getint(),return x -> apply(f.apply(x));

}

default Function andThen(Function f) {

return x -> f.apply(apply(x));

}

java函数调用?}

这是一个函数式接口,因为它只有一个抽象方法,接口中存在的默认方法不会影响到它的定义。

区别如图所示:

8fe41aa303ad0d6f6a0f28e1de21d7d6.png函数复合

我们可以看出这两个方法存在冗余,因为g.compose(f)与f.andThen(g)完全等价。

注:在使用Java官方提供的函数式接口时,你会遇到名为@FunctionalInterface的注解,

js函数式编程。@FunctionalInterface

public interface Function {

……//仅含有一个抽象方法

}

这个标识性注解告诉编译器,这个类将被设计成函数式接口,有且仅有一个抽象方法。如果你用了这个注解但接口却定义了多个抽象方法

java编程思想。@FunctionalInterface

public interface Function {

U apply(T t);

void f();

}

java,这时编译器会提示你:

Invalid '@FunctionalInterface' annotation; Function is not a functional interface。

但这个注解不是必须的,你也可以不使用它,只要你的接口符合函数式接口的规范。然而,在编写函数式接口时使用它仍是一个好习惯。

方法引用

如果你觉得lambda难懂或麻烦,在某些情况下,可以用方法引用这种快捷写法代替。

请看下面的例子:fff9567b09d63004c8cfc03692a14d03.png

函数?实例方法引用和类型的实例方法引用可能有点难以理解,实例方法引用,就是调用已经存在的实例的方法,这个对象实例是lambda表达式外部的实例。而类型的实例方法要求Lambda 参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数。

而对于构造函数的引用,根据构造函数参数的不同,可分为:

假设这有个类User{

……//

}

java函数式编程有必要吗、无参

Supplier supplier= User::new;

User user = supplier.get();

一个参数(假设参数类型为T):

Function function = User::new;

函数柯里化的意义、User user = function.apply(t);

两个参数(假设类型分别为T,U):

我们定义一个函数式接口

interface BiFunction(T,U,R){

R apply(T t,U u);

Java函数式编程,}

BiFunction  biFunction = User::new;

User user = biFunction.app(t,u);

其他的以此类推。我们需要有与构造方法匹配的函数式接口。

高阶函数及相关特性

java响应式编程?如果一个函数(Java里称作方法)有多个参数,我们能永远将它看作只有一个参数的函数,而我们所做的,就是使用元组。函数有两个参数,可以说它有一个二元组参数,三个参数、四个参数亦是如此。例如,在scala里,我们可以简单定义一个元组,val t3= (1,2.0,”3”)  。它可以通过t3._1访问第一个元素,t3._2访问第二个元素,以此类推。

遗憾的是,Java并不支持元组类型,好在我们可以用类和泛型自定义自己的元组使用。例如二元组Tuple2、三元组Tuple3等。

下面是一个元组定义的例子,这是一个二元元组。

public class Tuple {

public final T _1;

public final U _2;

public Tuple(T _1, U _2) {

super();

this._1 = _1;

this._2 = _2;

}

@Override

public String toString() {

return "Tuple = [" + _1 + "][" + _2 + "]";

}

}

柯里化

在上一章中,我曾介绍过一个函数:

public static Function f(String args,Function> g){

return g.apply(args);

}

我说过,这和函数的柯里化有关,接下来我将想你介绍何为柯里化和部分施用。这两个概念极易混肴。某种意义上说,他们产生的效果,得到的结果是一样的,以至于在Groovy语言里,把他们统称为了柯里化。

简单来说,柯里化就是把一个多参函数转化为一串串单参函数的过程,参数可以一个接一个应用,除了最后一个参数外,其他参数都会产生一个全新的函数。

例如对函数F(X,Y,Z),柯里化后将会得到F(X)(Y)(Z)。你可决定到底对多少个参数实施变换。而部分使用就是提前带入一部分具体的参数值,部分求解后得到一个参数较少的函数。

例如对函数F(X,Y,Z),我们提前施用X的值,将会得到F(Y,Z)。

对于函数Function>来说,它会接受一个String类型的参数,并返回一个String->Integer类型的参数 。

例如:

f("abs",s->x->s.length()+x.length()).apply("abcds")

这个函数执行的结果为8,它只是将两个字符串的长度相加而已。实际上具体多少参数不做限制,只是Java里写起函数类型太麻烦。在Scala里,你可以这样表示:

f (“abs”) (“abcds”)。

对于上面这种可以接受函数作为参数,也可以将函数作为结果返回的函数,我们称之为高阶函数。

下一篇中,我将通过定义一个列表List,这个列表更加符合函数式的数据结构。同时通过这个列表向大家介绍函数式编程的三板斧,filter,map,fold.即过滤,映射,折叠(部分语言称为reduce归约)。

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/67773.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息