当サイトは、アフィリエイト広告を利用しています
java8のstreamAPIのfilter等を使ってオブジェクトのArrayListの
重複チェックをする方法をメモしておく。
※以外によく使うので
当ブログで紹介しているjava8のstreamAPIを使った
コレクションや配列の操作方法を
下記記事でメソッド別にまとめています!
streamAPIのdistinctでは重複チェックする値(キー)の
設定はできないのでオブジェクトの特定のプロパティで重複削除はできない
また、全プロパティで比較してもオブジェクトは参照アドレスで比較されるので
distinctでは重複を削除できない
HashSetの要素の重複を許可しない特性を使って
ArrayListのremoveIfで重複要素の削除を行うパターン
Setにキーをそのまま追加する
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {//重複チェックキーとするidを重複させるPerson pob1 = new Person(1,"TANAKA","東京",11);Person pob2 = new Person(2,"YAMADA","京都",12);Person pob3 = new Person(3,"KOJIMA","東京",13);Person pob4 = new Person(3,"MAJIMA","富山",13);Person pob5 = new Person(4,"MAJIMA","富山",13);//list作成List<Person>pList = new ArrayList<>();pList.add(pob1);pList.add(pob2);pList.add(pob3);pList.add(pob4);pList.add(pob5);//セット作成HashSet<Integer> seen = new HashSet<>();//removeIfで重複削除//idをキーにするpList.removeIf(p->!seen.add(p.getId()));System.out.println(pList);}}// [{1 TANAKA 東京 11}, {2 YAMADA 京都 12}, {3 KOJIMA 東京 13}, {4 MAJIMA 富山 13}]
Setに追加するときに文字列結合して作ったキーを追加する
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {//重複チェックキーとするnameとaddressを重複させるPerson pob1 = new Person(1,"TANAKA","東京",11);Person pob2 = new Person(2,"YAMADA","京都",12);Person pob3 = new Person(3,"KOJIMA","東京",13);Person pob4 = new Person(3,"MAJIMA","富山",13);Person pob5 = new Person(4,"MAJIMA","富山",13);//list作成List<Person>pList = new ArrayList<>();pList.add(pob1);pList.add(pob2);pList.add(pob3);pList.add(pob4);pList.add(pob5);//セット作成HashSet<String> seen = new HashSet<>();//removeIfで重複削除//名前と住所の複合キーを作るpList.removeIf(p->!seen.add(p.getName() + p.getAddress()));System.out.println(pList);}}// [{1 TANAKA 東京 11}, {2 YAMADA 京都 12}, {3 KOJIMA 東京 13}, {3 MAJIMA 富山 13}]
重複キーが一つの場合の動作を確認する
CollectorsクラスのcollectingAndThenとtoCollectionを使うことでも
重複削除できる。
import java.util.*;import java.util.Comparator;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {Person pob1 = new Person(1,"TANAKA","東京",11);Person pob2 = new Person(2,"YAMADA","京都",12);Person pob3 = new Person(3,"KOJIMA","東京",13);Person pob4 = new Person(4,"MAJIMA","富山",13);Person pob5 = new Person(4,"KOYAMA","東京",13);List<Person>pList = new ArrayList<>();pList.add(pob1);pList.add(pob2);pList.add(pob3);pList.add(pob4);pList.add(pob5);//住所をキーにするList<Person> unique = pList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(p->p.getAddress()))),ArrayList::new));//idをキーにするList<Person> unique2 = pList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparingLong(p->p.getId()))),ArrayList::new));// 重複オブジェクトSystem.out.println(unique);System.out.println(unique2);}}// [{2 YAMADA 京都 12}, {4 MAJIMA 富山 13}, {1 TANAKA 東京 11}]// [{1 TANAKA 東京 11}, {2 YAMADA 京都 12}, {3 KOJIMA 東京 13}, {4 MAJIMA 富山 13}]
ちょっとわかりにくいような気もする。。。
動作確認する
重複しているレコードを削除ではなくで取得したい場合は
filterの中で同じlistに対してfilterして
重複しているレコードのみを抽出する
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {//住所が重複してるオブジェクトを作成Person pob1 = new Person(1,"TANAKA","東京",11);Person pob2 = new Person(2,"YAMADA","京都",12);Person pob3 = new Person(3,"KOJIMA","東京",13);Person pob4 = new Person(3,"MAJIMA","富山",13);Person pob5 = new Person(3,"KOYAMA","東京",13);//listに追加List<Person>pList = new ArrayList<>();pList.add(pob1);pList.add(pob2);pList.add(pob3);pList.add(pob4);pList.add(pob5);//重複オブジェクトの抽出List<Person>resultList = pList.stream().filter(p1->{List<Person>inList = pList.stream().filter(p2->p1.getAddress().equals(p2.getAddress())).collect(Collectors.toList());;//2件以上あれば重複しているif(inList.size() > 1){return true;}else{return false;}}).collect(Collectors.toList());// 重複オブジェクトSystem.out.println(resultList);}}// [{1 TANAKA 東京 11}, {3 KOJIMA 東京 13}, {3 KOYAMA 東京 13}]
重複しているレコードを特定する必要がなく、ただ重複しているかだけ
確かめたい場合はdistinctを使う。
オブジェクトでないlistの場合はstreamのdistictを使うことで判定できる
import java.util.*;import java.util.stream.Collectors;import java.util.stream.*;public class Main {public static void main(String[] args) throws Exception {List<String>list = new ArrayList<>();list.add("aaa");list.add("bbb");list.add("aaa");System.out.println(pList.size() == pList.stream().distinct().count());// 重複要素が存在する場合false}}
オブジェクトのリストの場合はできないので重複したレコードを取得したい場合と同様に
するしかなさそう
javaでコーディング時に重複チェック処理をstreamAPIを使ってできないかと思い
調べたり、考えてみたらできる方法があった。
Setを利用するなどの別のクラスの特性などを利用する方法は
まったく思いつかなかった。