java - 基于条件和顺序的 Java 8 lambda 过滤
问题描述
我试图根据多个条件过滤列表,排序。
class Student{
private int Age;
private String className;
private String Name;
public Student(int age, String className, String name) {
Age = age;
this.className = className;
Name = name;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
现在,如果我有一份清单,请说
List<Student> students = new ArrayList<>();
students.add(new Student(24, "A", "Smith"));
students.add(new Student(24, "A", "John"));
students.add(new Student(30, "A", "John"));
students.add(new Student(20, "B", "John"));
students.add(new Student(24, "B", "Prince"));
我如何才能获得具有不同名字的最年长学生的列表?在 C# 中,通过使用 System.Linq GroupBy 然后比较然后用 select 展平,这将非常简单,我不太确定如何在 Java 中实现相同的效果。
解决方案
使用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>
.
推荐阅读
- angular - “节点上的点击事件”是否适用于有角度的美人鱼 js?
- android - Android 如何在小屏幕上向左移动菜单
- laravel - Laravel QueryBuilder 多列匹配在同一个 WhereIn
- java - 从流中获取中间结果以稍后在流中使用
- python - 带有 SQLite 测试用例的 SQLAlchemy 日期时间
- python - 如何从值列表中准备批量数据?
- python - 如何在 Python 中检查 PDF 页面是否有颜色?
- amazon-web-services - 从发送地址回复 - AWS WORKMAIL
- python - Mapbox API 密钥问题
- javascript - 非 JS 注入