技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

java:重複を排除する方法3選

今回は、javaでListの重複排除を行う方法を3つ紹介します。
 
1つ目の方法は、for文で自力でアルゴリズムを記述して重複排除を行う方法です。
記述が冗長になり、コーディングミスも起こりやすいことから、現在の実務ではこの方法で重複排除を行うことはないと思います。
しかし、新人研修でjavaの標準APIの学習が不十分な段階で使うケースが想定される他、実務でもCOBOLからjavaにコンバージョンしている等のレガシーな環境では見かけることがあるかもしれません。
 
2つ目の方法は、HashSet(順番を保証する必要がある場合はLinkedHashSet)を使用する方法です。
HashSetとは、重複を排除して要素を格納するクラスであり、自力で重複排除のアルゴリズムを記述する必要がないためコーディングミスは起こりにくいです。
コンストラクタでListとSetの相互変換も可能であることもあり、記述も簡潔になります。
実務ではHashSetを使うケースが多いと思います。
 
3つ目の方法は、StreamAPIを使用する方法です。
StreamAPIにはdistinctメソッドが用意されており、このメソッドを呼び出すことで重複排除が可能です。
Java8から導入された機能であり、背景に関数型プログラミングの考え方があることから、昔からjavaを書いてきた人は取っつきにくさを感じるかもしれません。
しかし、新しい物好きの現場ではStreamAPIの使用が好まれるでしょう。
 
以下、サンプルコードです。
 
【サンプルコード】
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class DistinctMain {

  public static void main(String[ ] args) {

    // 重複排除前のList
    List<Integer> beforeList = new ArrayList<Integer>();
    beforeList.add(1);
    beforeList.add(3);
    beforeList.add(2);
    beforeList.add(4);
    beforeList.add(3);
    beforeList.add(2);
    beforeList.add(1);

    // 重複排除後のList
    // 期待結果:1→3→2→4
    List<Integer> afterList1;
    List<Integer> afterList2;
    List<Integer> afterList3;

    // for文で重複排除
    // 値を一つ一つ抽出、未抽出の値なら出力のListに詰め、抽出済の値なら無視
    afterList1 = new ArrayList<Integer>();
    for (int i = 0; i < beforeList.size(); i++) {
      int item = beforeList.get(i);
      int j = 0;
      for (; j < afterList1.size(); j++) {
        if (item == afterList1.get(j)) {
          break;
        }
      }
      if (j == afterList1.size()) {
        afterList1.add(item);
      }
    }

    // LinkedHashSetで重複排除(HashSetだと順番が保証されない)
    // コンストラクタを利用してList→Set(重複排除)→Listの変換
    Set<Integer> tmpSet = new LinkedHashSet<Integer>(beforeList);
    afterList2 = new ArrayList<Integer>(tmpSet);

    // StreamAPIで重複排除
    // Streamに変換→distinctメソッドで重複排除→Listに変換
    afterList3 = beforeList.stream()
                .distinct()
                .collect(Collectors.toList());

    // 重複排除結果の確認
    System.out.println("[for文で重複排除]");
    for (int item : afterList1) {
      System.out.println(item);
    }
    System.out.println("[LinkedHashSetで重複排除]");
    for (int item : afterList2) {
      System.out.println(item);
    }
    System.out.println("[StreamAPIで重複排除]");
    for (int item : afterList3) {
      System.out.println(item);
    }

  }

}
 
【実行結果】
[for文で重複排除]
1
3
2
4
[LinkedHashSetで重複排除]
1
3
2
4
[StreamAPIで重複排除]
1
3
2
4