Mar*_*ark 0 java functional-programming java-8 functional-interface
Java 8 添加了函数式编程结构,包括Function类及其关联identity()方法。
这是此方法的当前结构:
// Current implementation of this function in the [JDK source][1]
static <T> Function<T, T> identity() {
return t -> t;
}
// Can be used like this
List<T> sameList = list.stream().map(Function.identity()).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
但是,还有第二种构造它的方法:
// Alternative implementation of the method
static <T> T identity(T in) {
return in;
}
// Can be used like this
List<T> sameList = list.stream().map(Function::identity).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
甚至还有第三种方式来构建它:
// Third implementation
static final Function<T, T> IDENTITY_FUNCTION = t -> t;
// Can be used like this
List<T> sameList = list.stream().map(Function.IDENTITY_FUNCTION).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
在这三种方法中,JDK 中实际使用的第一种方法看起来内存效率较低,因为它似乎在每次使用时都创建一个新对象 (lambda),而第二个和第三个实现则没有。根据this SO answer,实际情况并非如此,因此最终所有三种方法在性能方面似乎都相对相同。
使用第二种方法允许将该方法用作方法参考,这类似于在函数构造中使用多少其他标准库方法。例如stream.map(Math::abs)或stream.map(String::toLowerCase)。
总的来说,为什么使用第一种方法,它看起来(虽然最终不是)性能较差并且与其他示例不同?
TL;DR UsingFunction.identity()仅创建一个对象,因此内存效率很高。
第三个实现不编译,因为T未定义,所以这不是一个选项。
在第二种实现中,每次编写时都会创建Function::identity一个新的对象实例。
在第一个实现中,无论何时调用Function.identity(),都会返回同一个lambda 对象的实例。
自己看很简单。首先identity在同一个类中创建这两个方法,因此将它们重命名为identity1并identity2保持它们分别可识别。
static <T> Function<T, T> identity1() {
return t -> t;
}
static <T> T identity2(T in) {
return in;
}
Run Code Online (Sandbox Code Playgroud)
编写一个test接受 aFunction并打印对象的方法,这样我们就可以看到它的唯一标识,正如哈希码所反映的那样。
static <A, B> void test(Function<A, B> func) {
System.out.println(func);
}
Run Code Online (Sandbox Code Playgroud)
test重复调用该方法以查看每个方法是否获得了一个新的对象实例(我的代码在一个名为 的类中Test)。
test(Test.identity1());
test(Test.identity1());
test(Test.identity1());
test(Test::identity2);
test(Test::identity2);
for (int i = 0; i < 3; i++)
test(Test::identity2);
Run Code Online (Sandbox Code Playgroud)
输出
static <T> Function<T, T> identity1() {
return t -> t;
}
static <T> T identity2(T in) {
return in;
}
Run Code Online (Sandbox Code Playgroud)
如您所见,调用all 的多个语句Test.identity1()获取相同的对象,但使用all 的多个语句Test::identity2获取不同的对象。
确实,重复执行同一条语句会获得相同的对象(如循环结果所示),但这与从不同语句获得的结果不同。
结论: UsingTest.identity1()只创建一个对象,所以它比 using 更节省内存Test::identity2。
| 归档时间: |
|
| 查看次数: |
423 次 |
| 最近记录: |