基于 Java 8 中的属性从对象列表中删除重复项 [英] Remove duplicates from a list of objects based on property in Java 8

查看:39
本文介绍了基于 Java 8 中的属性从对象列表中删除重复项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从基于某些属性的对象列表中删除重复项.

I am trying to remove duplicates from a List of objects based on some property.

我们可以使用 java 8 以简单的方式做到这一点吗

can we do it in a simple way using java 8

List<Employee> employee

我们可以根据员工的 id 属性从中删除重复项吗?我看到过从字符串数组列表中删除重复字符串的帖子.

Can we remove duplicates from it based on id property of employee. I have seen posts removing duplicate strings form arraylist of string.

推荐答案

您可以从 List 中获取一个流并将其放入您提供的 TreeSet唯一比较 id 的自定义比较器.

You can get a stream from the List and put in in the TreeSet from which you provide a custom comparator that compares id uniquely.

如果你真的需要一个列表,你可以把这个集合放回一个 ArrayList 中.

Then if you really need a list you can put then back this collection into an ArrayList.

import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

...
List<Employee> unique = employee.stream()
                                .collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparingInt(Employee::getId))),
                                                           ArrayList::new));

举个例子:

List<Employee> employee = Arrays.asList(new Employee(1, "John"), new Employee(1, "Bob"), new Employee(2, "Alice"));

它会输出:

[Employee{id=1, name='John'}, Employee{id=2, name='Alice'}]


另一个想法可能是使用一个包装器来包装员工,并根据其 id 使用 equals 和 hashcode 方法:


Another idea could be to use a wrapper that wraps an employee and have the equals and hashcode method based with its id:

class WrapperEmployee {
    private Employee e;

    public WrapperEmployee(Employee e) {
        this.e = e;
    }

    public Employee unwrap() {
        return this.e;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        WrapperEmployee that = (WrapperEmployee) o;
        return Objects.equals(e.getId(), that.e.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(e.getId());
    }
}

然后包装每个实例,调用 distinct(),解开它们并将结果收集到列表中.

Then you wrap each instance, call distinct(), unwrap them and collect the result in a list.

List<Employee> unique = employee.stream()
                                .map(WrapperEmployee::new)
                                .distinct()
                                .map(WrapperEmployee::unwrap)
                                .collect(Collectors.toList());


事实上,我认为您可以通过提供一个进行比较的函数来使这个包装器通用:


In fact, I think you can make this wrapper generic by providing a function that will do the comparison:

public class Wrapper<T, U> {
    private T t;
    private Function<T, U> equalityFunction;

    public Wrapper(T t, Function<T, U> equalityFunction) {
        this.t = t;
        this.equalityFunction = equalityFunction;
    }

    public T unwrap() {
        return this.t;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        @SuppressWarnings("unchecked")
        Wrapper<T, U> that = (Wrapper<T, U>) o;
        return Objects.equals(equalityFunction.apply(this.t), that.equalityFunction.apply(that.t));
    }

    @Override
    public int hashCode() {
        return Objects.hash(equalityFunction.apply(this.t));
    }
}

并且映射将是:

.map(e -> new Wrapper<>(e, Employee::getId))

这篇关于基于 Java 8 中的属性从对象列表中删除重复项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆