Java 8 lambdas,Function.identity()或t-> t
我有一个关于Function.identity()
方法的用法的问题。
想象下面的代码:
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.
是否有任何理由,你应该使用Function.identity()
而不是str->str
(反之亦然)。 我认为第二个选项更具可读性(当然是品味)。 但是,有什么“真正的”理由为什么应该被优先考虑呢?
就目前的JRE实现而言, Function.identity()
将始终返回相同的实例,而identifier -> identifier
每次出现不仅会创build自己的实例,甚至还会有一个独特的实现类。 有关更多细节,请参阅此处 。
原因是编译器生成一个保存该lambdaexpression式的普通主体的合成方法(在x->x
的情况下,等价于return identifier;
),并且指示运行时创build调用此方法的函数接口的实现。 所以运行时只能看到不同的目标方法,而目前的实现并不能分析方法来找出某些方法是否等价。
因此,使用Function.identity()
而不是x -> x
可能会节省一些内存,但是如果您真的认为x -> x
比Function.identity()
更具可读性,则不应该推动您的决定。
您也可以考虑,在启用debugging信息的情况下进行编译时,合成方法将具有指向包含lambdaexpression式的源代码行的行debugging属性,因此您可以find特定Function
实例的源代码debugging。 相反,在debugging操作期间遇到由Function.identity()
返回的实例时,您将不知道是谁调用了该方法并将该实例传递给该操作。
在你的例子中, str -> str
和Function.identity()
之间没有很大的区别,因为它在内部只是t->t
。
但有时我们不能使用Function.identity
。 看看这里
List<Integer> list = new ArrayList<>(); list.add(1); list.add(2);
这将编译好
int[] arrayOK = list.stream().mapToInt(i -> i).toArray();
但如果你会尝试编译
int[] arrayProblem = list.stream().mapToInt(Function.identity()).toArray();
你将得到编译错误,因为mapToInt
需要ToIntFunction
,它与Function
无关。 ToIntFunction
也没有identity()
方法。
来自JDK源 :
static <T> Function<T, T> identity() { return t -> t; }
所以,不,只要它在语法上是正确的。