Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么Predicate.isEqual的实现方式是这样的?_Java_Java 8 - Fatal编程技术网

Java 为什么Predicate.isEqual的实现方式是这样的?

Java 为什么Predicate.isEqual的实现方式是这样的?,java,java-8,Java,Java 8,最近我一直在摆弄新的java8特性,以便更好地理解它们 在尝试使用Stream.filter时,我遇到了Predicate.java的源代码,在其中我发现了isEqual方法的以下实现: /** * Returns a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)}. * * @param <T> the type of

最近我一直在摆弄新的java8特性,以便更好地理解它们

在尝试使用
Stream.filter
时,我遇到了
Predicate.java
的源代码,在其中我发现了
isEqual
方法的以下实现:

/**
 * Returns a predicate that tests if two arguments are equal according
 * to {@link Objects#equals(Object, Object)}.
 *
 * @param <T> the type of arguments to the predicate
 * @param targetRef the object reference with which to compare for equality,
 *               which may be {@code null}
 * @return a predicate that tests if two arguments are equal according
 * to {@link Objects#equals(Object, Object)}
 */
static <T> Predicate<T> isEqual(Object targetRef) {
    return (null == targetRef)
            ? Objects::isNull
            : object -> targetRef.equals(object);
}
在我看来,这是一个不必要的lambda的创造

除非我错过了什么,否则对我来说,他们也一样。(他们是相同的权利吗?)选择当前实施的原因是什么?或者这仅仅是一件非常小的事情,只是被忽视了,或者没有人真正关心

我猜这实际上导致了一个额外的问题:使用一种方法比另一种方法有什么好处吗?比如某种(可能很小的)绩效奖金

为什么要这样做

纯粹是猜测,但可能在编写时,开发人员对->和可能的::更为熟悉,当时甚至不起作用。这些库是在修复编译器中的错误时编写的

没有办法知道,甚至写这本书的人也可能不记得了


无论使用方法引用还是闭包语法,在大多数情况下都会创建相同数量的对象(如本例所示)

我猜这实际上导致了一个额外的问题:使用一种方法比另一种方法有什么好处吗?比如某种(可能很小的)绩效奖金

使用方法引用意味着少调用一个方法。这可能会对内联产生间接影响,因为默认情况下级别数限制为9。比如说

import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) {
        Consumer<String> lambda = s-> printStackTrace(s);
        lambda.accept("Defined as a lambda");

        Consumer<String> methodRef = Main::printStackTrace;
        methodRef.accept("Defined as a method reference");
    }


    static void printStackTrace(String description) {
        new Throwable(description).printStackTrace();
    }
}
在第一种情况下,编译器生成了一个名为
Main.lambda$Main$0
的方法,其中包含实际调用
printStackTrace

使用一个或另一个会产生更大差异的地方是,您可以使用捕获(保存值)或不捕获lambda。非捕获lambda只创建一次

e、 g

Consumer print1=System.out::println;//每次创建一个对象
消费者打印2=s->System.out.println(s);//创建一个对象一次。

在第一种情况下,如果调用
System.setOut
,它将忽略此更改,因为它有自己的打印流副本要写入。

方法引用与显式lambda在同一台研磨机中结束。这两种方法都需要相同的实现技术。我认为没有人能够回答这个问题。。。希望是编写代码的人。。。即使这样,也不太确定。这是谓词工厂,每个流构造只调用一次。在这两种情况下,都有相同的函数接口实例,其方法正在被调用。这一切都完全一样。@OlleKelderman运行时没有真正的区别。方法引用比较干净,但在运行时,所做的工作量和创建的对象数量是相同的。@OlleKelderman有一点,但最好理解其中的差异,即使在99%的时间里,这并不重要。看到我的答案了。至于为什么会这样做的最初问题,我猜答案是“我们很可能永远都不知道,而且这可能不重要”@OlleKelderman现在想象一组lambda,在第一种情况下,如果你把它加两次,你会得到一组2,在第二种情况下,你会得到一组1。尝试删除一个,您可能会分别得到2和0的大小。@OlleKelderman可能在编写时,开发人员对
->
更为熟悉,可能
当时甚至不起作用。这些库是在修复编译器中的错误时编写的@MarkoTopolnik在lambda风格的语法中,一个
静态
方法被添加到包含实际代码的类中,一个对该生成方法的方法引用被添加到字节码中。如果使用方法引用语法,则不会添加此额外的静态方法,这意味着内联的级别减少了一个。由于表达式包含
Objects::isNull
,因此作者不太可能“对->更满意”,也不太可能::不起作用。可能是
instance::method
表单不起作用或者作者不知道,但是似乎对::操作符有偏好,否则,它将是
object->Objects.isNull(object)
import java.util.function.Consumer;

public class Main {
    public static void main(String[] args) {
        Consumer<String> lambda = s-> printStackTrace(s);
        lambda.accept("Defined as a lambda");

        Consumer<String> methodRef = Main::printStackTrace;
        methodRef.accept("Defined as a method reference");
    }


    static void printStackTrace(String description) {
        new Throwable(description).printStackTrace();
    }
}
java.lang.Throwable: Defined as a lambda
    at Main.printStackTrace(Main.java:15)
    at Main.lambda$main$0(Main.java:6)
    at Main.main(Main.java:7)

java.lang.Throwable: Defined as a method reference
    at Main.printStackTrace(Main.java:15)
    at Main.main(Main.java:10)
Consumer<String> print1 = System.out::println; // creates an object each time
Consumer<String> print2 = s->System.out.println(s); // creates an object once.