概要
JavaもStreamの機能が実装されてから、Listから重複削除(distinct)が行えるようになりました。ただ、【Java8】Streamで重複削除(& 重複チェック)の記事にある通り、標準の機能ではListの値のみで重複削除が可能であり、Listがオブジェクトの場合にオブジェクトの中の指定したキーで重複削除が行えません。
ということで、今回はどのようにしたらオブジェクトの中の指定したキーで重複削除を実現できるか、というのを書いてみます。
対応候補
Stream.distinctをフィールド・プロパティなどで行うにはの記事にある通り、distinctを使わずにfilterとHashSetを組み合わせて重複削除を実現する方法が紹介されています。また、Java 8 Distinct by propertyの記事には、groupingByを使う方法やクラスをWrapperする方法、ライブラリを使う方法が紹介されています。
方法は色々あって、どれでも良いかなとは思うのですが、今回はRxJava
のライブラリを使う方法を紹介します。
<2020/11/13追記>
@Rui_K さんのコメントで紹介頂いた記事Java8のStream distinctを使用する方法では、標準Streamのdistinctの内部処理ではequalsが使われているようです。なので、equalsメソッドに同一判定のロジックを実装すれば、標準のメソッドでも対応できそう。
RxJavaを使った重複削除
RxJavaとは今さらながらのRxJava - 概要編の記事に紹介されている通り、リアクティブプログラミングを実現するために開発されたライブラリです。RxJavaで用意されているObservableクラスにおいてdistinctメソッドが用意されていて、このメソッドでは重複対象とするキーを指定することができます。こちらのドキュメントを参照ください。
サンプルコードは以下の通りです。ここではUserクラスのemailの値で重複削除を行っています。
List<User> distinctUserRecords = Observable.fromStream(userRecords.stream())
.distinct(u -> u.getEmail()).toList().blockingGet();