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
因为Strings 的自然顺序是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 具有流中所有Strings 的最大长度。这是 Comparator.comparing 的预期用例,在使用方法引用时可以使其更具可读性,即 Comparator.comparing(String::length) 几乎不言自明……