将命名函数作为参数传递
Java 8添加了lambda表达式。 以类似于匿名类的方式使用lambdas非常简单,但我想知道是否存在使用命名函数作为其他函数的参数的相关function。 例如,是否有Java方法来编写以下Python代码:
list1 = (1,2,3) list2 = (4,5,6) def add(a, b): return a+b for e in map(add, list1, list2): print(e)
产量
5 7 9
是的,您可以使用Integer::sum
等方法引用,其中允许使用lambdas。
int six = IntStream.of(1, 2, 3) .reduce(0, Integer::sum);
这相当于
int six = IntStream.of(1, 2, 3) .reduce(0, (a, b) -> Integer.sum(a, b));
在Java 8中添加了像Integer.sum
和Double.max
这样的方法,因此它们可以像这样用在lambda中。
但是,没有像Python那样将多个列表“压缩”在一起的内置方法。
好吧,Java中没有“函数”,只有方法,所以你不会得到同样的东西。
实现此目的的最佳方法是使用方法引用 ,在这种情况下可以使用BiConsumer
:
import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.function.BiConsumer; public class StackOverflow { public static void main(String[] args) throws InterruptedException { List list1 = new ArrayList<>(); list1.add(1); list1.add(2); list1.add(3); List list2 = new ArrayList<>(); list2.add(4); list2.add(5); list2.add(6); mapOver(StackOverflow::add, list1, list2); } public static void add(Integer a, Integer b) { System.out.println(a + b); } public static void mapOver(BiConsumer function, Iterable first, Iterable second) { final Iterator firstIterator = first.iterator(); final Iterator secondIterator = second.iterator(); while (firstIterator.hasNext() && secondIterator.hasNext()) { function.accept(firstIterator.next(), secondIterator.next()); } } }
输出:
5 7 9
不确定你的问题究竟是什么,但在Java中,这将是……
List { System.out.println(list1.get(i) + list2.get(i)); });
..因为你不能像在python中那样在Java中流式传输多个集合。
当然可以声明其类型是function接口的变量,然后为它们分配lambdas。 这是这个答案及其评论主题的结论。 例如,一个人可能有这样的声明:
BiFunction add = (a, b) -> a + b;
这不是OP所要求的。 Python的等价物如下:
add = lambda a, b: a + b
这不是命名函数; 它是一个变量,其值是(lambda)函数。 最初的问题是询问在Java中使用命名函数。 这样做的方法是使用方法引用。
假设您有一个采用BiFunction
参数的方法。 你可以传递上面定义的add
变量。 但您也可以声明一个普通方法,并将其用作方法引用的目标。 诀窍是确保“形状”(参数的数量和类型,返回值的类型)与您尝试使用的任何function接口相匹配。 在这种情况下,您有两个Integer
类型的参数,返回值为Integer
,因此您的方法将是
static Integer add(Integer a, Integer b) { return a + b; }
然后你可以使用MyClass::add
forms的方法引用来引用它。
请注意,我已将其设为静态方法。 如果它是实例方法,则接收器( this
)是一个隐藏参数,在将其与function接口匹配时必须考虑该参数。
另请注意,由于自动装箱,还可以写:
static int add(int a, int b) { return a + b; }
当然可以将lambda用于变量,例如,如果在运行时选择算法。 但是如果将lambda全部分配给常量字段,则使用针对普通方法的方法引用通常更容易。