在Java中使用Lambda表达式查找Max

时间:2014-06-24 05:01:18

标签: java lambda max java-8

这是我的代码

    List<Integer> ints = Stream.of(1,2,4,3,5).collect(Collectors.toList());
    Integer maxInt = ints.stream()
                              .max(Comparator.comparing(i -> i))
                              .get();

    System.out.println("Maximum number in the set is " + maxInt);

输出:

Maximum number in the set is 5

我不能在我的代码的下面两个i之间进行distingues

Comparator.comparing(i -> i)

任何人都可以善待并解释两个i之间的差异吗?

3 个答案:

答案 0 :(得分:21)

方法Comparator.comparing(…)旨在创建一个Comparator,它使用基于对象属性进行比较的顺序。当使用lambda表达式i -> i(这是(int i) -> { return i; }的简写)时,作为属性提供程序函数,生成的Comparator将比较值本身。当要比较的对象具有Integer自然顺序时,此方法有效。

所以

Stream.of(1,2,4,3,5).max(Comparator.comparing(i -> i))
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));

相同
Stream.of(1,2,4,3,5).max(Comparator.naturalOrder())
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));

虽然后者效率更高,因为它实现为具有自然顺序的所有类型的单例(并实现Comparable)。

max完全需要Comparator的原因是因为您使用的是可能包含任意对象的泛型类Stream

这允许,例如像streamOfPoints.max(Comparator.comparing(p->p.x))一样使用它来查找具有最大x值的点,而Point本身没有自然顺序。或者执行streamOfPersons.sorted(Comparator.comparing(Person::getAge))

之类的操作

使用专门的IntStream时,您可以直接使用自然顺序,这可能更有效:

IntStream.of(1,2,4,3,5).max()
.ifPresent(maxInt->System.out.println("Maximum number in the set is " + maxInt));

说明“自然顺序”与基于属性的顺序之间的区别:

Stream.of("a","bb","aaa","z","b").max(Comparator.naturalOrder())
.ifPresent(max->System.out.println("Maximum string in the set is " + max));

这将打印

  

集合中的最大字符串是z

因为String s的自然顺序是z大于b且大于a的词典顺序

另一方面

Stream.of("a","bb","aaa","z","b").max(Comparator.comparing(s->s.length()))
.ifPresent(max->System.out.println("Maximum string in the set is " + max));

将打印

  

集合中的最大字符串是aaa

因为aaa具有流中所有String的最大长度。这是Comparator.comparing的预期用例,在使用方法引用时可以使其更具可读性,即Comparator.comparing(String::length)几乎可以说明自己......

答案 1 :(得分:4)

此功能(注意->用于闭包,不要与用于比较的=>混淆)

i -> i

只是意味着您需要按原样比较整个对象。即如果我有i,您需要比较i

一个不太重要的例子可能是

max(Comparator.comparing(i -> -i))

会给你最小或

max(Comparator.comparing(i -> Math.abs(100-i))

为您提供距离100最远的值。

max(Comparator.comparing(i -> i.toString()))

这将给你最大的比较作为一个字符串,即&#34; 9&#34; &GT; &#34; 10&#34;作为一个字符串。

答案 2 :(得分:0)

Comparator.comparing需要一个将源对象映射到实际得到的值的函数 - 在您的情况下,因为您不希望预处理要比较的值,i是只是映射到自己。