Java 8のプロパティに基づいてオブジェクトのリストから重複を削除する [重複] 質問する

Java 8のプロパティに基づいてオブジェクトのリストから重複を削除する [重複] 質問する

あるプロパティに基づいてオブジェクトのリストから重複を削除しようとしています。

Java 8を使って簡単な方法でできますか?

List<Employee> employee

id従業員のプロパティに基づいて重複を削除できますか。文字列の配列リストから重複した文字列を削除する投稿を見たことがあります。

ベストアンサー1

からストリームを取得しList、 に配置してTreeSet、ID を一意に比較するカスタム コンパレータを提供することができます。

リストが本当に必要な場合は、このコレクションを 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 メソッドを使用するというものがあります。

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()、ラップを解除し、結果をリストに収集します。

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

実際、比較を行う関数を提供することで、このラッパーを汎用化できると思います。

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))

おすすめ記事