有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么不支持流。最大接受整数。作为输入参数进行比较?

小溪。max方法接受一个比较器,但不接受整数。compare不实现Comparator接口。唯一的相似之处是它们共享compare()方法的相同方法签名。所以我很困惑,成为比较器输入参数的先决条件是什么?多谢各位

例如:

List<Integer> ls = Arrays.asList(9,2,5,8); 
System.out.println(ls.stream().max(Integer::compare).get());

共 (3) 个答案

  1. # 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

    If the form is ReferenceType :: [TypeArguments] Identifier, the body of the invocation method similarly has the effect of a method invocation expression for a compile-time declaration which is the compile-time declaration of the method reference expression...
    ...

    • If the compile-time declaration is an instance method, then the target reference is the first formal parameter of the invocation method. Otherwise, there is no target reference.

    • If the compile-time declaration is an instance method, then the arguments to the method invocation expression (if any) are the second and subsequent formal parameters of the invocation method. Otherwise, the arguments to the method invocation expression are the formal parameters of the invocation method.

    描述如何解析、验证和调用方法引用的详细信息太多,无法在此处包含,因此阅读JLS的这一部分绝对是一个好主意:-)

  2. # 2 楼答案

    ^{} interface是函数接口,因此可以使用其方法签名符合函数接口的任何lambda表达式或方法引用

    compare方法获取两个对象,对它们进行比较,并返回一个int用于排序。方法引用Integer::compare引用了^{}'s ^{} method,并且该方法的签名匹配,因此编译器允许该方法引用解析为Comparator实例

    当将Lambda表达式和方法引用作为参数传递给方法、赋值给变量以及作为参数传递给强制转换运算符时,允许使用Lambda表达式和方法引用。这里,方法引用作为参数传递给方法,因此编译器将其视为合法代码

  3. # 3 楼答案

    因为在此上下文中,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);
        }
    }