Java 8 lambdas、Function.identity() 或 t->t
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28032827/
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
Java 8 lambdas, Function.identity() or t->t
提问by
I have a question regarding the usage of the Function.identity()
method.
我有一个关于该Function.identity()
方法使用的问题。
Imagine the following code:
想象一下以下代码:
Arrays.asList("a", "b", "c")
.stream()
.map(Function.identity()) // <- This,
.map(str -> str) // <- is the same as this.
.collect(Collectors.toMap(
Function.identity(), // <-- And this,
str -> str)); // <-- is the same as this.
Is there any reason why you should use Function.identity()
instead of str->str
(or vice versa). I think that the second option is more readable (a matter of taste of course). But, is there any "real" reason why one should be preferred?
有什么理由你应该使用Function.identity()
而不是str->str
(反之亦然)。我认为第二个选项更具可读性(当然是品味问题)。但是,是否有任何“真正”的理由为什么应该优先考虑?
回答by Pshemo
In your example there is no big difference between str -> str
and Function.identity()
since internally it is simply t->t
.
在您的示例中,str -> str
和之间没有太大区别,Function.identity()
因为在内部它只是t->t
.
But sometimes we can't use Function.identity
because we can't use a Function
. Take a look here:
但有时我们不能使用,Function.identity
因为我们不能使用Function
. 看看这里:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
this will compile fine
这将编译正常
int[] arrayOK = list.stream().mapToInt(i -> i).toArray();
but if you try to compile
但是如果你尝试编译
int[] arrayProblem = list.stream().mapToInt(Function.identity()).toArray();
you will get compilation error since mapToInt
expects ToIntFunction
, which is not related to Function
. Also ToIntFunction
doesn't have identity()
method.
由于mapToInt
expects ToIntFunction
,您将收到编译错误,这与Function
. 也ToIntFunction
没有identity()
办法。
回答by JasonN
From the JDK source:
从JDK 源代码:
static <T> Function<T, T> identity() {
return t -> t;
}
So, no, as long as it is syntactically correct.
所以,不,只要它在语法上是正确的。
回答by Holger
As of the current JRE implementation, Function.identity()
will always return the same instance while each occurrence of identifier -> identifier
will not only create its own instance but even have a distinct implementation class. For more details, see here.
对于当前的 JRE 实现,Function.identity()
将始终返回相同的实例,而每次出现时identifier -> identifier
不仅会创建自己的实例,而且还会有一个不同的实现类。有关更多详细信息,请参阅此处。
The reason is that the compiler generates a synthetic method holding the trivial body of that lambda expression (in the case of x->x
, equivalent to return identifier;
) and tell the runtime to create an implementation of the functional interface calling this method. So the runtime sees only different target methods and the current implementation does not analyze the methods to find out whether certain methods are equivalent.
原因是编译器生成一个合成方法,该方法包含该 lambda 表达式的简单主体(在 的情况下x->x
,相当于return identifier;
)并告诉运行时创建调用此方法的函数式接口的实现。所以运行时只看到不同的目标方法,当前的实现不会分析这些方法来找出某些方法是否等效。
So using Function.identity()
instead of x -> x
might save some memory but that shouldn't drive your decision if you really think that x -> x
is more readable than Function.identity()
.
因此,使用Function.identity()
而不是x -> x
可能会节省一些内存,但如果您真的认为它x -> x
比Function.identity()
.
You may also consider that when compiling with debug information enabled, the synthetic method will have a line debug attribute pointing to the source code line(s) holding the lambda expression, therefore you have a chance of finding the source of a particular Function
instance while debugging. In contrast, when encountering the instance returned by Function.identity()
during debugging an operation, you won't know who has called that method and passed the instance to the operation.
您还可以考虑在启用调试信息的情况下编译时,合成方法将有一个 line debug 属性指向包含 lambda 表达式的源代码行,因此您有机会Function
在调试时找到特定实例的源. 相比之下,Function.identity()
在调试操作期间遇到返回的实例时,您将不知道是谁调用了该方法并将实例传递给了操作。