在Java 8中,方法可以创建为Lambda表达式,并且可以通过引用传递(在底层做一些工作)。网上有很多创建lambdas并将其与方法一起使用的示例,但没有示例说明如何创建以lambda作为参数的方法。它的语法是什么?

MyClass.method((a, b) -> a+b);


class MyClass{
  //How do I define this method?
  static int method(Lambda l){
    return l(5, 10);
  }
}

当前回答

基本上,要将lambda表达式作为参数传递,我们需要一个可以保存它的类型。就像我们在原始int或integer类中持有的整数值一样。Java没有单独的lambda表达式类型,而是使用接口作为类型来保存参数。但是这个接口应该是一个功能接口。

其他回答

Lambda表达式可以作为参数传递。要将lambda表达式作为参数传递,形参的类型(接收lambda表达式作为参数)必须为函数接口类型。

如果有功能接口-

interface IMyFunc {
   boolean test(int num);
}

还有一个filter方法,它只在int值大于5时才将int值添加到列表中。这里注意,filter方法有函数接口IMyFunc作为参数之一。在这种情况下,lambda表达式可以作为方法参数的参数传递。

public class LambdaDemo {
    public static List<Integer> filter(IMyFunc testNum, List<Integer> listItems) {
        List<Integer> result = new ArrayList<Integer>();
        for(Integer item: listItems) {
            if(testNum.test(item)) {
                result.add(item);
            }
        }
        return result;
    }
    public static void main(String[] args) {
        List<Integer> myList = new ArrayList<Integer>();
        myList.add(1);
        myList.add(4);
        myList.add(6);
        myList.add(7);
        // calling filter method with a lambda expression
        // as one of the param
        Collection<Integer> values = filter(n -> n > 5, myList);

        System.out.println("Filtered values " + values);
    }
}

下面是c#如何处理这个问题(但是用Java代码表示)。像这样的东西几乎可以满足你所有的需求:

import static org.util.function.Functions.*;

public class Test {

    public static void main(String[] args)
    {
        Test.invoke((a, b) -> a + b);       
    }

    public static void invoke(Func2<Integer, Integer, Integer> func)
    {
        System.out.println(func.apply(5, 6));
    }
}

package org.util.function;

public interface Functions {

    //Actions:
    public interface Action {
        public void apply();
    }

    public interface Action1<T1> {
        public void apply(T1 arg1);
    }

    public interface Action2<T1, T2> {
        public void apply(T1 arg1, T2 arg2);
    }

    public interface Action3<T1, T2, T3> {
        public void apply(T1 arg1, T2 arg2, T3 arg3);
    }

    public interface Action4<T1, T2, T3, T4> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
    }

    public interface Action5<T1, T2, T3, T4, T5> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
    }

    public interface Action6<T1, T2, T3, T4, T5, T6> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
    }

    public interface Action7<T1, T2, T3, T4, T5, T6, T7> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
    }

    public interface Action8<T1, T2, T3, T4, T5, T6, T7, T8> {
        public void apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
    }

    //Functions:
    public interface Func<TResult> {
        public TResult apply();
    }

    public interface Func1<T1, TResult> {
        public TResult apply(T1 arg1);
    }

    public interface Func2<T1, T2, TResult> {
        public TResult apply(T1 arg1, T2 arg2);
    }

    public interface Func3<T1, T2, T3, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3);
    }

    public interface Func4<T1, T2, T3, T4, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
    }

    public interface Func5<T1, T2, T3, T4, T5, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
    }

    public interface Func6<T1, T2, T3, T4, T5, T6, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
    }

    public interface Func7<T1, T2, T3, T4, T5, T6, T7, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
    }

    public interface Func8<T1, T2, T3, T4, T5, T6, T7, T8, TResult> {
        public TResult apply(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
    }
}

有一个支持lambda的Java 8 JavaDocs的公共web可访问版本,链接到http://lambdafaq.org/lambda-resources。(这显然应该是对Joachim Sauer的回答的评论,但我无法进入我的SO帐户,我需要声望点来添加评论。)lambdafaq站点(由我维护)回答了这个问题和许多其他Java-lambda问题。

注意:这个答案是在Java 8 GA文档公开之前写的。不过,我把它留在了原处,因为Lambda FAQ对于学习Java 8中引入的特性的人来说可能仍然有用。

这很简单。lambda表达式的目的是实现函数接口。它是只有一个方法的接口。这里有一篇关于预定义和遗留功能接口的很棒的文章。

不管怎样,如果你想实现你自己的功能接口,那就做吧。举个简单的例子:

public interface MyFunctionalInterface {
    String makeIt(String s);
}

所以让我们创建一个类,在这里我们将创建一个方法,它接受MyFunctionalInterface的类型:

public class Main {

    static void printIt(String s, MyFunctionalInterface f) {
        System.out.println(f.makeIt(s));
    }

    public static void main(String[] args) {

    }
}

你应该做的最后一件事是将MyFunctionalInterface的实现传递给我们已经定义的方法:

public class Main {

    static void printIt(String s, MyFunctionalInterface f) {
        System.out.println(f.makeIt(s));
    }

    public static void main(String[] args) {
        printIt("Java", s -> s + " is Awesome");
    }
}

就是这样!

对于不超过2个参数的函数,可以传递它们而无需定义自己的接口。例如,

class Klass {
  static List<String> foo(Integer a, String b) { ... }
}

class MyClass{

  static List<String> method(BiFunction<Integer, String, List<String>> fn){
    return fn.apply(5, "FooBar");
  }
}

List<String> lStr = MyClass.method((a, b) -> Klass.foo((Integer) a, (String) b));

在bifuncfunction <Integer, String, List<String>>中,Integer和String是其参数,List<String>是其返回类型。

对于只有一个形参的函数,可以使用function <T, R>,其中T是它的形参类型,R是它的返回值类型。有关Java已经提供的所有接口,请参阅此页。