stream.max方法采用Comparator,但Integer.compare不实现Comparator接口。唯一的相似之处是它们共享compare()方法的相同方法签名。因此,对于成为比较器输入参数的先决条件有什么困惑?谢谢。
示例:
List<Integer> ls = Arrays.asList(9,2,5,8);
System.out.println(ls.stream().max(Integer::compare).get());
答案 0 :(得分:2)
在这种情况下,Integer::compare
等同于其lambda形式:
(a, b) -> Integer.compare(a, b)
这种lambda形式在逻辑上也等同于其匿名类形式:
new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return Integer.compare(a, b);
}
}
答案 1 :(得分:2)
Comparator
interface是一个功能接口,因此可以使用其方法签名符合该功能接口的任何lambda表达式或方法引用。
compare
方法将两个对象进行比较,然后返回int
以进行排序。方法引用Integer::compare
引用了Integer
's compare
method,并且该方法的签名匹配,因此编译器允许此方法引用解析为Comparator
实例。
Lambda表达式和方法引用。在这里,您的方法引用将作为参数传递给方法,因此编译器将其视为合法代码。
答案 2 :(得分:1)
Integer.compare(int, int)
有一个签名,可用于实现Comparator<Integer>.compare(Integer, Integer)
。由于Comparator
是一个功能接口,因此我们可以使用对Integer.compare
的方法引用来提供Comparator<Integer>
的实现。
此表单使用static
方法Integer.compare(int, int)
。
在这种情况下,当流比较两个元素时,它将进行以下静态调用:
Integer.compare(element1, element2);
Integer::compare
可用于提供具有相同签名的任何功能接口的实现,例如:
BinaryOperator<Integer> bo = Integer::compare; //int functName(int, int)
BiFunction<Integer, Integer, Integer> bf = Integer::compare;
//or even
BiConsumer<Integer, Integer> bc = Integer::compare; //return value ignored
方法引用的另一种形式是使用:
System.out.println(ls.stream().max(Integer::compareTo).get());
在这种情况下,要比较两个元素,流将调用:
element1.compareTo(element2);
第二种形式使用实例变体integer.compareTo(otherInteger)
(在这种情况下,当流将元素一一二比较时,在运行时解析用作目标和参数的实际实例)。
这是基于:
JLS-15.13.3 Run-Time Evaluation of Method References:
如果格式为ReferenceType :: [TypeArguments]标识符,则调用方法的主体类似地具有编译时声明的方法调用表达式的效果,该编译时声明是方法引用表达式的编译时声明。 。
...
如果编译时声明是一个实例方法,则目标引用是调用方法的第一个形式参数。否则,将没有目标引用。
如果编译时声明是实例方法,则方法调用表达式的参数(如果有)是调用方法的第二个和后续形式参数。否则,方法调用表达式的参数是调用方法的形式参数。
描述方法引用的解析,验证和调用方式的详细信息太多了,因此这里不涉及它,因此遍历JLS的这一部分绝对是一个好主意:-)