根据条件从List <object>中删除重复项

时间:2018-10-19 08:32:55

标签: java list java-8 set

起点:

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最大的条件。

4 个答案:

答案 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)中添加值。