【问题标题】:Java 8 Lambdas max() on stream using Integer.max as comparator [duplicate]使用 Integer.max 作为比较器的 Java 8 Lambdas max() [重复]
【发布时间】:2016-07-03 19:17:33
【问题描述】:

我用示例值编写了简单的List,我希望流从流返回最大值。我知道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());
}

输出:

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 ???

我的问题:

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

【问题讨论】:

  • 你应该使用Integer::conmpareTo,而不是Integer::max...
  • 您也可以使用reduce(Integer::max);,因为取最大值是一个关联操作,但这与max(Integer::compare)几乎相同
  • 1) 的答案:这就是方法引用的工作方式。如果方法的签名合适,就可以;没有“智能检查”可以防止这种情况发生。 2) 的答案:如果你告诉 max 方法 5&gt;3&gt;85&gt;8 这就是你得到的......

标签: java lambda java-8


【解决方案1】:

你误会了。 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());
}

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

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

关于您问题的第二部分,请参阅:: (double colon) operator in 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());

【讨论】:

    【解决方案2】:

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

    如果比较AB,如果A 更小,则应返回-1。您返回ABInteger.max,在您的情况下,它始终是&gt;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;
    }
    

    【讨论】:

    • 啊!我懂了!总结一下:我的 max 函数的输出应该返回 -101,而我这里的总是返回正数。因此第一个参数,这里调用a 总是赢。我说的对吗?
    • @mlewandowski 是的。您还可以在列表中试验负值,看看会发生什么;)
    • 输出不一定是严格的-1+1。它可以是任何整数值,但重要的是结果的含义是负数、零还是正数。
    • @Holger 是的,这是正确的,感谢您添加评论。我只是为这个例子简化了它。
    【解决方案3】:

    不幸的是,Integer.max 代替比较器进行编译的原因是它的返回类型符合流的max 方法所期望的:比较的结果是int,比较的结果是两个ints 也是一个int。但是,Integer.max 返回的结果与流的max 期望的结果不一致,这说明结果不正确:例如,如果将(5, 8) 传递给Integer.max,则返回8,一个正数;但是,流的max 将所有正数解释为第一个参数大于第二个参数的指示,在这种情况下这是不正确的。

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

    【讨论】:

      猜你喜欢
      • 2023-03-09
      • 2020-02-09
      • 2019-03-13
      • 1970-01-01
      • 2023-04-04
      • 2015-10-11
      • 2017-10-28
      • 2015-11-02
      • 2011-05-05
      相关资源
      最近更新 更多