fge*_*fge 213 java java-8 java-stream
注意:这个问题源于一个死链接,这是以前的SO问题,但是这里......
看到这个代码(注意:我不知道,这个代码将不能"工作",而Integer::compare
应使用-我只是提取它从链接的问题):
final ArrayList <Integer> list
= IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());
System.out.println(list.stream().max(Integer::max).get());
System.out.println(list.stream().min(Integer::min).get());
Run Code Online (Sandbox Code Playgroud)
据javadoc的.min()
和.max()
,两者的参数应该是一个Comparator
.然而,这里的方法引用是Integer
类的静态方法.
那么,为什么要编译呢?
Dav*_*oyd 242
让我解释一下这里发生了什么,因为它并不明显!
首先,Stream.max()
接受一个实例,Comparator
以便可以将流中的项目相互比较以找到最小值或最大值,以一些您不需要过多担心的最佳顺序.
所以问题当然是为什么被Integer::max
接受了?毕竟它不是比较器!
答案就是新的lambda功能在Java 8中的工作方式.它依赖于一种非正式地称为"单一抽象方法"接口或"SAM"接口的概念.这个想法是任何带有一个抽象方法的接口都可以通过任何lambda或方法引用自动实现 - 其方法签名与接口上的一个方法匹配.所以检查Comparator
界面(简单版本):
public Comparator<T> {
T compare(T o1, T o2);
}
Run Code Online (Sandbox Code Playgroud)
如果一个方法正在寻找a Comparator<Integer>
,那么它基本上是在寻找这个签名:
int xxx(Integer o1, Integer o2);
Run Code Online (Sandbox Code Playgroud)
我使用"xxx",因为方法名称不用于匹配目的.
因此,无论是Integer.min(int a, int b)
和Integer.max(int a, int b)
是足够接近,自动装箱会允许这种情况出现的Comparator<Integer>
一个方法上下文.
Jon*_*eet 116
Comparator
是一个功能界面,并Integer::max
符合该界面(考虑自动装箱/拆箱后).它需要两个int
值并返回int
- 正如您所期望的那样Comparator<Integer>
(再次,斜视忽略Integer/int差异).
不过,我不希望它做正确的事情,因为Integer.max
它不符合语义的Comparator.compare
.事实上,它确实不起作用.例如,做一个小改动:
for (int i = 1; i <= 20; i++)
list.add(-i);
Run Code Online (Sandbox Code Playgroud)
...现在max
值为-20,min
值为-1.
相反,两个调用都应该使用Integer::compare
:
System.out.println(list.stream().max(Integer::compare).get());
System.out.println(list.stream().min(Integer::compare).get());
Run Code Online (Sandbox Code Playgroud)
ski*_*iwi 19
这有效,因为Integer::min
解析了Comparator<Integer>
接口的实现.
Integer::min
解决Integer.min(int a, int b)
,解决IntBinaryOperator
和可能自动装箱的方法参考发生在使其成为的地方BinaryOperator<Integer>
.
并且要求实现接口的min()
resp max()
方法.
现在这解决了单一方法.哪种类型.Stream<Integer>
Comparator<Integer>
Integer compareTo(Integer o1, Integer o2)
BinaryOperator<Integer>
因此,两种方法都是一种魔力BinaryOperator<Integer>
.
归档时间: |
|
查看次数: |
144780 次 |
最近记录: |