将命名函数作为参数传递

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.sumDouble.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::addforms的方法引用来引用它。

请注意,我已将其设为静态方法。 如果它是实例方法,则接收器( this )是一个隐藏参数,在将其与function接口匹配时必须考虑该参数。

另请注意,由于自动装箱,还可以写:

 static int add(int a, int b) { return a + b; } 

当然可以将lambda用于变量,例如,如果在运行时选择算法。 但是如果将lambda全部分配给常量字段,则使用针对普通方法的方法引用通常更容易。