使用Integer.max作为比较器的Java 8 Lambdas max()

mle*_*ski 3 java lambda java-8

我用简单List的示例值写了,我希望流从Stream返回最大值.我知道max()功能需要,Comparator但事实证明,我也可以通过Integer::max(任何人都可以解释我的,为什么?).

此外,程序打印出奇怪的结果,我在"内部"检查它看起来没问题,但在我得到最终结果后 - 它们不准确.

例:

@Test
public void testHowIntegerMaxWorksInStream() {
    List<Integer> list = Arrays.asList(5,3,8);
    Optional<Integer> op = list.stream().max((a, b) -> {
        System.out.println("Input arguments a=" + a + ", b=" + b);

        int max = Integer.max(a, b);
        System.out.println("Returning max(a,b)=" + max);
        return max;
    });
    System.out.println("Optional result=" + op.get());
}
Run Code Online (Sandbox Code Playgroud)

输出:

Input arguments a=5, b=3
Returning max(a,b)=5
Input arguments a=5, b=8
Returning max(a,b)=8 // OK, Integer::max got 8.. but then ...
Optional result=5 // .. I got 5. WHY ???
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 为什么我可以Integer::max代替Comparator
  2. 为什么我的函数在8的内部返回5?

Tun*_*aki 6

你是在误解事物.max(comparator)采用比较整数的比较器.你所做的不是比较整数,即告诉是否a大于b或等.你拿走了他们的最大值并将其归还.所以你说这a总是大于b,因为你总是返回一个正数(你的列表只包含正数).一个Comparator回报:

第一个参数的负整数,零或正整数小于,等于或大于第二个参数.

你需要做的是

public void testHowIntegerMaxWorksInStream() {
    List<Integer> list = Arrays.asList(5,3,8);
    Optional<Integer> op = list.stream().max((a, b) -> {
        int compare = Integer.compare(a, b);
        return compare;
    });
    System.out.println("Optional result=" + op.get());
}
Run Code Online (Sandbox Code Playgroud)

即调用Integer.compare而不是max,这正是这样做:

比较它的两个参数的顺序.返回负整数,零或正整数,因为第一个参数小于,等于或大于第二个参数.

对于问题的第二部分,请参阅Java 8中的::(双冒号)运算符.它被称为方法 - 反射.所以写另一种方法是:

List<Integer> list = Arrays.asList(5,3,8);
Optional<Integer> op = list.stream().max(Integer::compare);
System.out.println("Optional result=" + op.get());
Run Code Online (Sandbox Code Playgroud)


das*_*ght 5

其原因Integer.max,不幸的是,编译代替比较的是,它的返回类型适合什么是流的预期max方法:比较的结果是int,并比较两者的结果ints是一个int为好.但是,返回的结果Integer.max与流的max预期不一致,这解释了不正确的结果:例如,如果传递(5, 8)Integer.max它返回8,则为正数; max然而,流将所有正数解释为第一个参数大于第二个参数的指示,这在这种情况下是不正确的.

这个编译的唯一原因是你的比较器返回一个int.这不适用于DoubleBigInteger.


Rob*_*bAu 1

因为您创建的比较器总是返回最大的第一个元素。

如果你比较AB,你应该返回-1ifA更小。您返回Integer.maxofAB,在您的情况下,它始终是>0

(a,b) -> { 
   if (a>b) return 1;     // <-- you return a positive value always, so stream.max() thinks 5>8 :)
   if (a<b) return -1;
   if (a==b) return 0;
}
Run Code Online (Sandbox Code Playgroud)