Java 8 中带有 2 个箭头的 lambda 是啥意思?
Posted
技术标签:
【中文标题】Java 8 中带有 2 个箭头的 lambda 是啥意思?【英文标题】:What does lambda with 2 arrows mean in Java 8?Java 8 中带有 2 个箭头的 lambda 是什么意思? 【发布时间】:2015-12-25 13:28:10 【问题描述】:我之前读过几篇 Java 8 教程。
现在我遇到了以下话题: Does java support Currying?
在这里,我看到以下代码:
IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));
我知道这个示例包含 2 个元素,但我无法理解结构:
a -> b -> a + b;
根据表达式的左边部分,该行应实现以下功能:
R apply(int value);
在此之前,我只遇到过只有一个箭头的 lambdas。
【问题讨论】:
你明白柯里化是什么意思吗?这对这个问题非常重要。 只是一个返回 lambda 的 lambda。 【参考方案1】:如果您将其表达为非速记 lambda 语法或 pre-lambda Java 匿名类语法,那么发生了什么会更清楚......
原来的问题。为什么是两个箭头?很简单,定义了两个函数……第一个函数是函数定义函数,第二个是该函数的结果,也恰好是函数。每个都需要一个->
运算符来定义它。
非速记
IntFunction<IntUnaryOperator> curriedAdd = (a) ->
return (b) ->
return a + b;
;
;
Java 8 之前的 Pre-Lambda
IntFunction<IntUnaryOperator> curriedAdd = new IntFunction<IntUnaryOperator>()
@Override
public IntUnaryOperator apply(final int value)
IntUnaryOperator op = new IntUnaryOperator()
@Override
public int applyAsInt(int operand)
return operand + value;
;
return op;
;
【讨论】:
pre-lambda 需要final int value
是的,你是对的,但我写的仍然是使用 Java 8 编译器,它允许你使用“有效最终”的东西
@g*** 是的,但是 java 8 不是 pre-lambda
你也可以在 java 8 中使用 pre-lambda 样式。我写的 JFY
不是 lambdas 只是为了让人们得分吗? :-)【参考方案2】:
IntFunction<R>
是一个函数 int -> R
。 IntUnaryOperator
是一个函数 int -> int
。
因此IntFunction<IntUnaryOperator>
是一个以int
作为参数并返回以int
作为参数并返回int
的函数的函数。
a -> b -> a + b;
^ | |
| ---------
| ^
| |
| The IntUnaryOperator (that takes an int, b) and return an int (the sum of a and b)
|
The parameter you give to the IntFunction
如果您使用匿名类来“分解” lambda,也许会更清楚:
IntFunction<IntUnaryOperator> add = new IntFunction<IntUnaryOperator>()
@Override
public IntUnaryOperator apply(int a)
return new IntUnaryOperator()
@Override
public int applyAsInt(int b)
return a + b;
;
;
【讨论】:
【参考方案3】:添加括号可能会更清楚:
IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
或者中间变量可能会有所帮助:
IntFunction<IntUnaryOperator> curriedAdd = a ->
IntUnaryOperator op = b -> a + b;
return op;
;
【讨论】:
【参考方案4】:让我们用括号重写那个 lambda 表达式以使其更清楚:
IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));
所以我们声明了一个函数,它接受一个int
,它返回一个Function
。更具体地说,返回的函数接受 int
并返回 int
(两个元素的总和):这可以表示为 IntUnaryOperator
。
因此,curriedAdd
是一个接受int
并返回IntUnaryOperator
的函数,因此它可以表示为IntFunction<IntUnaryOperator>
。
【讨论】:
【参考方案5】:这是两个 lambda 表达式。
IntFunction<IntUnaryOperator> curriedAdd =
a -> //this is for the fixed value
return b -> //this is for the add operation
return a + b;
;
IntUnaryOperator addTwo = curriedAdd.apply(2);
System.out.println(addTwo.applyAsInt(12)); //prints 14
【讨论】:
【参考方案6】:如果您查看IntFunction
,它可能会变得更清楚:IntFunction<R>
是FunctionalInterface
。它表示一个接受int
并返回R
类型值的函数。
在这种情况下,返回类型R
也是FunctionalInterface
,即IntUnaryOperator
。所以 first(外部)函数本身返回一个函数。
在这种情况下:当应用于 int
时,curriedAdd
应该返回一个再次采用 int
的函数(并再次返回 int
,因为这是 IntUnaryOperator
所做的)。
在函数式编程中,将函数的类型写成param -> return_value
是很常见的,你在这里可以看到。所以curriedAdd
的类型是int -> int -> int
(或者int -> (int -> int)
,如果你更喜欢的话)。
Java 8 的 lambda 语法也随之而来。要定义这样一个函数,你写
a -> b -> a + b
这与实际的 lambda 演算非常相似:
λa λb a + b
λb a + b
是一个函数,它接受单个参数 b
并返回一个值(总和)。 λa λb a + b
是一个接受单个参数a
并返回单个参数的另一个函数的函数。 λa λb a + b
返回 λb a + b
并将 a
设置为参数值。
【讨论】:
以上是关于Java 8 中带有 2 个箭头的 lambda 是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章