Stream.max(Integer :: max):意外结果

时间:2016-03-20 20:03:55

标签: java java-8 compare max java-stream

我正在使用Enthuware的模拟测试来学习1z0-809 : Java SE 8 Programmer II

遇到这个问题。

List<Integer> ls = Arrays.asList(3,4,6,9,2,5,7);

System.out.println(ls.stream().reduce(Integer.MIN_VALUE, (a, b)->a>b?a:b)); //1
System.out.println(ls.stream().max(Integer::max).get()); //2
System.out.println(ls.stream().max(Integer::compare).get()); //3
System.out.println(ls.stream().max((a, b)->a>b?a:b)); //4   
     

以上哪个陈述会打印9?

答案是

  

1和3

但还有别的东西。我不明白为什么

System.out.println(ls.stream().max(Integer::max).get()); // PRINTS 3

我尝试使用peek进行调试,但它并不能帮助我理解。

我尝试使用lsInteger::max

Integer::compare进行排序
ls.sort(Integer::max);     // [3, 4, 6, 9, 2, 5, 7]
ls.sort(Integer::compare); // [2, 3, 4, 5, 6, 7, 9]

当然,我认为Integer::max不是比较器,因此它具有相同的签名。 对我来说,max在第一种情况下应为7,因为它是最后一个元素,就像我使用Ìnteger::compare

排序时一样

有人可以把它分解成简单的东西吗?

5 个答案:

答案 0 :(得分:11)

您需要更换

.max(Integer::max)

.max(Integer::compare)

这里的问题是抽象方法compare被声明返回一个int值,并且Integer.max的签名和方法中的方法Integer.compare也被满足。 Integer类,因此表示Integer::max被推断为有效的Comparator。尽管可以像这样实现比较方法:

  

返回负整数,零或正整数作为第一个   参数小于,等于或大于第二个。

在您当前的情况下,代码总是以返回正值(给定输入)而结束,因此,比较中的第一个元素总是被认为更大,因此相应地返回。

答案 1 :(得分:10)

Integer.max(a, b)将返回给定ab的更大值。如果您以某种方式将该结果用作比较器,则返回的正值将被视为a > b所以a将被保留。

前两个元素是3和4.两者都是正数。 Integer.max(3, 4) = 4 > 0。所以你用这样的比较器有效地说3 > 4,所以保留3。然后,其余部分也是如此:Integer.max(3, 6) = 6 > 0,因此3被认为是最大等等。

答案 2 :(得分:6)

比较方法的合同(关于参数firstsecond)是:

    如果first等于second ,则
  • 返回0
  • 如果first < second
  • 则返回否定值
  • 如果first > second
  • 则返回正值

仅具有正值的max方法将始终返回正值。根据比较器合同解释返回值时,正值表示first > second。因此,项目的顺序不会改变,它们似乎是“有序的”。

答案 3 :(得分:6)

这令人难以置信地令人困惑。

我们正在尝试使用Integer::max作为比较器。由于问题中的所有数字都是正数,因此答案总是被解释为compare(a, b)的第一个参数比第二个参数“更大”。

Collections.sort的一个怪癖是当你有一个列表[a, b]时,该方法的编程方式是compare(b, a)被调用,而不是compare(a, b) (这似乎更明智)。因此,如果compare返回正数,则它看起来像b > a,因此列表不需要排序。

这就是list.sort什么都不做的原因。

然而恰好Stream.max被编程反过来,即第一次比较是compare(3, 4),所以看起来3是最大值。

答案 4 :(得分:0)

尽管这不能回答问题,但可能的解决方案是:

try{
    int i = map.values().stream().mapToInt(e -> e).max().getAsInt();
}catch(NoSuchElementException e)
    e.printStackTrace();
}

mapToInt(e -> e)方法使用lambda表达式将流中的每个元素转换为整数值,然后返回IntStream,然后可以调用max()方法。 请注意,max()返回一个OptionalInteger,因此需要一个getAsInt()或一个orElse(0)方法调用。

您可以查看文档以获取更深入的答案:IntStreamOptionalInt