Java 使用方法引用而不是多参数 lambda

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23139725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:01:39  来源:igfitidea点击:

Using method reference instead of multi argument lambda

javalambdajava-8

提问by Majid Azimi

I'm confused about concept behind "Reference to an Instance Method of an Arbitrary Object of a Particular Type". Oracle documentationhas an example about this:

我对“引用特定类型的任意对象的实例方法”背后的概念感到困惑。Oracle文档中有一个关于此的示例:

String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
Arrays.sort(stringArray, String::compareToIgnoreCase);

Most of the examples I have seen for this kind of method reference is like this: If lambda is like: x -> x.func()then you can write it like ClassOfX::func. The example in documentation says:

我见过的大多数这种方法引用的例子都是这样的:如果 lambda 是这样的:x -> x.func()那么你可以像ClassOfX::func. 文档中的示例说:

The equivalent lambda expression for the method reference String::compareToIgnoreCase would have the formal parameter list (String a, String b), where a and b are arbitrary names used to better describe this example. The method reference would invoke the method a.compareToIgnoreCase(b).

方法引用 String::compareToIgnoreCase 的等效 lambda 表达式将具有形式参数列表 (String a, String b),其中 a 和 b 是用于更好地描述此示例的任意名称。方法引用将调用方法 a.compareToIgnoreCase(b)。

The question is: for any two argument lambda like (a, b) -> a.func(b)the funcmethod must be instance method of first argument and second argument of lambda will be passed as an argument to that method? If we have multiple argument lambda then funcmethod must be instance method of first argument of lambda and other arguments of lambda will be passed to funcin the order the appear in lambda? I mean instead of (a, b, c) -> a.func(b, c)we can write ClassOfA::func

问题是:对于任何两个参数的 lambda,如(a, b) -> a.func(b)func方法必须是第一个参数的实例方法,而 lambda 的第二个参数将作为参数传递给该方法?如果我们有多个参数 lambda,那么func方法必须是lambda的第一个参数的实例方法,并且 lambda 的其他参数将func按照出现在 lambda 中的顺序传递给?我的意思是(a, b, c) -> a.func(b, c)我们可以写ClassOfA::func

I'm sorry for my English. I hope I made the problem clear.

我为我的英语感到抱歉。我希望我把问题说清楚了。

采纳答案by ajb

SomeClass::funccan mean two things, depending on whether funcis a static method or an instance method.

SomeClass::func可能意味着两件事,取决于func是静态方法还是实例方法。

(1) If funcis a static method, then SomeClass::funcis a lambda that just passes all the arguments to the method:

(1) Iffunc是一个静态方法,则SomeClass::func是一个 lambda,它只是将所有参数传递给该方法:

(a, b, c) -> SomeClass.func(a, b, c);

(2) If funcis an instance method, then SomeClass::funcis a lambda that uses the first argument as the instance, as you thought:

(2) Iffunc是一个实例方法,那么SomeClass::func是一个使用第一个参数作为实例的 lambda,如你所想:

(a, b, c) -> a.func(b, c);

where ahas type SomeClass.

哪里a有类型SomeClass

EDIT:Sotirios' answer demonstrates yet a different type of method reference: example::methodwhere exampleis a reference variable (instead of a class name). This means the same as

编辑:Sotirios 的回答演示了另一种不同类型的方法引用:example::methodwhereexample是引用变量(而不是类名)。这意味着与

(a, b) -> example.method(a, b);

or perhaps more accurately

或者更准确地说

(a, b) -> __someFinalTemporary.method(a, b);

where __someFinalTemporaryis assigned to exampleat the point where the method reference is evaluated, so that if examplechanges later, the method is still called using the earlier value of example.

其中__someFinalTemporary被分配给example在其中该方法参考被评为点,因此,如果example变化后,该方法仍在使用的较早的值叫做example

[The fourth kind is SomeClass::newwhich passes the arguments to a constructor. I think that's all of them.]

[第四种是SomeClass::new将参数传递给构造函数。我想这就是他们的全部。]

回答by Louis Wasserman

I mean instead of (a, b, c) -> a.func(b, c) we can write ClassOfA::func

我的意思是代替 (a, b, c) -> a.func(b, c) 我们可以写 ClassOfA::func

Yes, that's correct.

对,那是正确的。

回答by Sotirios Delimanolis

Here's a small example demonstrating the behavior of an instance method reference.

这是一个演示实例方法引用行为的小示例。

public class Example {  
    public static void main(String[] args) throws Exception {
        List<String> strings = new ArrayList<String>();
        Example example = new Example();
        Functional methodRef = example::method;
        methodRef.funct("a string", strings);
        System.out.println("List now contains: " + strings);

        Functional lambda = (String s, List<String> l) -> {
            example.method(s, l);
        };
        lambda.funct("another string", strings);
        System.out.println("List now contains: " + strings);
    }

    interface Functional {
        void funct(String value, List<String> list);
    }

    void method(String value, List<String> toAddTo) {
        System.out.println("adding");
        toAddTo.add(value);
    }
}

It prints

它打印

adding
List now contains: [a string]
adding
List now contains: [a string, another string]

The two are more or less equivalent. In the lambda's case, the variable the method is invoked on needs to be effectively final.

两者或多或少是等价的。在 lambda 的情况下,调用方法的变量需要有效final

回答by Tao Zhang

According to Joshua Bloch in his "Effective Java" (3rd Edition), there are 5 types of use cases for method reference.

根据 Joshua Bloch 在他的“Effective Java”(第 3 版)中,有 5 种用例可供方法参考。

enter image description here

在此处输入图片说明