Использование коллектора toMap
:
Collection<Student> values = students.stream()
.collect(toMap(Student::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
.values();
Объяснение
Мы используем эту перегрузку toMap
:
toMap(Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
Student::getName
выше - это функция keyMapper
, используемая для извлечения значений для ключей карты. Function.identity()
выше - это функция valueMapper
, используемая для извлечениязначения для значений карты, где Function.identity()
просто возвращает элементы в источнике, который они сами, т.е. объекты Student
. BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))
выше - это функция слияния, используемая для «определения, какой объект Student будет возвращен вслучай ключевого столкновения, т. е. когда два заданных студента имеют одно и то же имя », в этом случае мы берем самое старое Student
. - Наконец, вызов
values()
возвращает нам коллекцию студентов.
Эквивалентный код C #:
var values = students.GroupBy(s => s.Name, v => v,
(a, b) => b.OrderByDescending(e => e.Age).Take(1))
.SelectMany(x => x);
Объяснение (для тех, кто не знаком с .NET)
Мы используем этот метод расширения GroupBy
:
System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult>
(this System.Collections.Generic.IEnumerable<TSource> source,
Func<TSource,TKey> keySelector,
Func<TSource,TElement> elementSelector,
Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
s => s.Name
выше - это функция keySelector
, используемая для извлечения значения в group by. v => v
выше - это elementSelector
функция, используемая для извлечения значений, т.е. Student
объекты сами по себе. b.OrderByDescending(e => e.Age).Take(1)
выше это resultSelector
, что даетIEnumerable<Student>
, представленный как b
, принимает самого старшего ученика. - Наконец, мы применяем
.SelectMany(x => x);
, чтобы свести получившееся IEnumerable<IEnumerable<Student>>
в IEnumerable<Student>
.