使用
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
函数用于提取要分组的值。v => v
上面的elementSelector
函数用于提取值,即Student
它们所拥有的对象。b.OrderByDescending(e => e.Age).Take(1)
以上是resultSelector
给出的IEnumerable<Student>
代表年龄b
最大的学生的。- 最后,我们申请
.SelectMany(x => x);
将结果折叠IEnumerable<IEnumerable<Student>>
成IEnumerable<Student>
。



