我对该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.
Run Code Online (Sandbox Code Playgroud)
是否有任何理由你应该使用Function.identity()而不是str->str(反之亦然).我认为第二种选择更具可读性(当然是品味问题).但是,有没有"真正的"理由为什么应该首选?
除了保存代码行之外,lambda表达式还有什么用处吗?
lambda提供的特殊功能是否解决了不容易解决的问题?我见过的典型用法是代替写这个:
Comparator<Developer> byName = new Comparator<Developer>() {
@Override
public int compare(Developer o1, Developer o2) {
return o1.getName().compareTo(o2.getName());
}
};
Run Code Online (Sandbox Code Playgroud)
我们可以使用lambda表达式来缩短代码:
Comparator<Developer> byName =
(Developer o1, Developer o2) -> o1.getName().compareTo(o2.getName());
Run Code Online (Sandbox Code Playgroud) 考虑我有以下代码:
class Foo {
Y func(X x) {...}
void doSomethingWithAFunc(Function<X,Y> f){...}
void hotFunction(){
doSomethingWithAFunc(this::func);
}
}
Run Code Online (Sandbox Code Playgroud)
假设hotFunction经常被调用.那么缓存是否可取this::func,也许是这样的:
class Foo {
Function<X,Y> f = this::func;
...
void hotFunction(){
doSomethingWithAFunc(f);
}
}
Run Code Online (Sandbox Code Playgroud)
就我对java方法引用的理解而言,虚拟机在使用方法引用时会创建匿名类的对象.因此,缓存引用将仅创建该对象一次,而第一种方法在每个函数调用上创建它.它是否正确?
是否应缓存出现在代码中热位置的方法引用,或者VM是否能够对此进行优化并使缓存变得多余?是否存在关于此的一般最佳实践,或者这种高度VM实现是否特定于此类缓存是否有用?
我在这里看到了很多关于Java lambdas性能的问题,但是大多数问题都像"Lambdas稍快一点,但在使用闭包时变慢"或"预热与执行时间不同"或其他类似的东西.
但是,我在这里遇到了一件相当奇怪的事情.考虑这个LeetCode问题:
给定一组非重叠间隔,在间隔中插入新间隔(必要时合并).
您可以假设间隔最初是根据其开始时间排序的.
问题被标记为难,所以我认为线性方法不是他们想要的.所以我决定想出一种聪明的方法将二进制搜索与修改结合到输入列表中.现在问题在修改输入列表时并不是很清楚 - 它表示"插入",即使签名需要返回对列表的引用,但现在也不用担心.这是完整的代码,但只有前几行与此问题相关.我在这里保留其余部分,以便任何人都可以尝试:
public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
int start = Collections.binarySearch(intervals, newInterval,
(i1, i2) -> Integer.compare(i1.start, i2.start));
int skip = start >= 0 ? start : -start - 1;
int end = Collections.binarySearch(intervals.subList(skip, intervals.size()),
new Interval(newInterval.end, 0),
(i1, i2) -> Integer.compare(i1.start, i2.start));
if (end >= 0) {
end += skip; // back to original indexes
} else {
end -= skip; // ditto
}
int newStart = newInterval.start;
int headEnd; …Run Code Online (Sandbox Code Playgroud) 我们知道匿名类维护对其封闭实例的引用,这可能导致Android上下文泄漏.
由于retrolambda backports中的lambda表达式来Java7,它可能是值得一试.
似乎 Java8 lambdas没有这个问题,但我找不到任何官方信息.
任何线索?
为什么我应该使用Function.identity()返回它收到的相同内容而不使用输入做任何事情或以某种方式修改输入?
Apple apple = new Apple(10, "green");
Function<Apple, Apple> identity = Function.identity();
identity.apply(apple);
Run Code Online (Sandbox Code Playgroud)
必须有一些实际用法,我无法弄清楚.
在获取流之前进行空检查的最佳/惯用方法是什么?
我有接收List可能为null的方法.所以我不能只调用.stream()传入的值.是否有一些静态助手,如果值为null,会给我一个空流?
如果我使用新语法获取方法引用:
anObject::aMethod
Run Code Online (Sandbox Code Playgroud)
我总是得到同一个对象吗?也就是说,我可以相信对同一方法的两个引用是相同的吗?
例如,我很乐意知道是否计划将它们用作Runnable我可以添加和删除的回调:
someLibrary.addCallback(anObject::aMethod)
// later
someLibrary.removeCallback(sameObject::sameMethod)
Run Code Online (Sandbox Code Playgroud)
这是否需要在Runnable变量中保存引用以保持其稳定?
请考虑以下代码片段:
public static Object o = new Object();
public static Callable x1() {
Object x = o;
return () -> x;
}
public static Callable x2() {
return () -> o;
}
Run Code Online (Sandbox Code Playgroud)
方法x2()将始终返回相同的lamba对象,而x1()始终会创建新的对象:
System.out.println(x1());
System.out.println(x1());
System.out.println(x2());
System.out.println(x2());
Run Code Online (Sandbox Code Playgroud)
会打印出这样的东西:
TestLambda$$Lambda$1/821270929@4a574795
TestLambda$$Lambda$1/821270929@f6f4d33
TestLambda$$Lambda$2/603742814@7adf9f5f
TestLambda$$Lambda$2/603742814@7adf9f5f
Run Code Online (Sandbox Code Playgroud)
哪里(在JVM规范中我猜?)是描述了这种lambda重用规则?JVM如何确定重用与否?
我偶然发现了以下使用方法参考的Java代码 System.out.println
class SomeClass{
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1,2,3,4,5,6,7,8,9);
numbers.forEach(System.out::println);
}
}
}
Run Code Online (Sandbox Code Playgroud)
什么是等效的lambda表达式System.out::println?