Ответ 1
Метод 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));
хотя последний более эффективен, поскольку он реализован как singleton для всех типов, которые имеют естественный порядок (и реализуют 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
является лексикографическим порядком, где 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)
, который почти говорит сам за себя...