gpt4 book ai didi

java - 为什么 Predicate.isEqual 是这样实现的?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:44:39 28 4
gpt4 key购买 nike

最近我一直在研究 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);
}

让我好奇的是这一行:: object -> targetRef.equals(object);

也许我想太多了,但我忍不住马上想到为什么那行不是 : targetRef::equals; 像这样:

static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: targetRef::equals;
}

在我看来,否则创建 lambda 是不必要的。

除非我遗漏了什么,否则对我来说那些都是一样的。 (它们是一样的吗?)选择当前实现有什么原因吗?或者这只是一件非常小的事情,它只是被忽视了,或者没有人真正关心过。

猜猜这实际上会导致一个额外的问题:使用一种方式比另一种方式有什么好处吗?喜欢某种(可能非常小的)绩效奖金?

最佳答案

Why was it done this way?

纯粹的猜测,但是,也许在编写它时开发人员对 -> 更满意,并且可能::当时甚至都不起作用。这些库是在修复编译器中的错误的同时编写的。

没有办法知道,甚至写它的人可能也不记得了。


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

Guess that actually results in a bonus question: Is there any benefit in using one way over the other? Like some kind of (probably very small) performance bonus?

使用方法引用意味着更少的方法调用。这可能会对内联产生间接影响,因为默认情况下级别数限制为 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();
}
}

打印

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)

在第一种情况下,编译器生成了一个名为 Main.lambda$main$0 的方法,其中包含实际调用 printStackTrace

的代码

当您可以使用捕获(保存值)或非捕获 lambda 时,使用其中一个或另一个会产生更大的不同。非捕获 lambda 仅创建一次。

例如

Consumer<String> print1 = System.out::println; // creates an object each time
Consumer<String> print2 = s->System.out.println(s); // creates an object once.

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

关于java - 为什么 Predicate.isEqual 是这样实现的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39957154/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com