起点:
public class Employee {
private String id;
private String name;
private String age;
}
我有一个员工列表:List<Employee> employee;
列表中的员工示例:
{id="1", name="John", age=10}
{id="2", name="Ana", age=12}
{id="3", name="John", age=23}
{id="4", name="John", age=14}
让我们假设age
是唯一的。
如何基于name
属性从列表中删除所有重复项,并将age
最大的条目保留在输出中?
输出应如下所示:
{id="2", name="Ana", age=12}
{id="3", name="John", age=23}
我的尝试方式:
HashSet<Object> temp = new HashSet<>();
employee.removeIf(e->!temp.add(e.getName()));
..但是这样,第一场比赛将保留在employee
{id="1", name="John", age=10}
{id="2", name="Ana", age=12}
...而且我不知道如何在此处设置另一个条件,以保持age
最大的条件。
答案 0 :(得分:5)
这是一种按name
对元素进行分组并通过选择最大值为age
的元素来减少组的方法:
List<Employee> uniqueEmployees = employees.stream()
.collect(Collectors.groupingBy(Employee::getName,
Collectors.maxBy(Comparator.comparing(Employee::getAge))))
.values()
.stream()
.map(Optional::get)
.collect(Collectors.toList());
哪个返回[[id=2, name=Ana, age=12], [id=3, name=John, age=23]]
和您的测试数据。
答案 1 :(得分:3)
除了accepted answer之外,还有两个变体:
int64
此人使用Collection<Employee> employeesWithMaxAge = employees.stream()
.collect(Collectors.toMap(
Employee::getName,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(Employee::getAge))))
.values();
按名称对员工进行分组,将Collectors.toMap
实例作为值。如果有同名员工,则使用第三个参数(二进制运算符)选择具有最大年龄的员工。
另一个变体也一样,但是不使用流:
Employee
或者,用Map<String, Employee> map = new LinkedHashMap<>(); // preserves insertion order
employees.forEach(e -> map.merge(
e.getName(),
e,
(e1, e2) -> e1.getAge() > e2.getAge() ? e1 : e2));
:
BinaryOperator.maxBy
答案 2 :(得分:1)
ernest_k 答案很好,但是如果您想避免添加重复项,可以使用以下方法:
public void addToEmployees(Employee e) {
Optional<Employee> alreadyAdded = employees.stream().filter(employee -> employee.getName().equals(e.getName())).findFirst();
if(alreadyAdded.isPresent()) {
updateAgeIfNeeded(alreadyAdded.get(), e);
}else {
employees.add(e);
}
}
public void updateAgeIfNeeded(Employee alreadyAdded, Employee newlyRequested) {
if(Integer.valueOf(newlyRequested.getAge()) > Integer.valueOf(alreadyAdded.getAge())) {
alreadyAdded.setAge(newlyRequested.getAge());
}
}
只需使用addToEmployees
方法将Employee
添加到您的列表中即可。
您还可以创建扩展ArrayList
的类并像这样覆盖add
方法,然后使用自己的列表:)
答案 3 :(得分:0)
仅当age大于等于地图中的值时,您才可以在Map<String, Employee>
(其中的字符串为name)中添加值。