java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

配列の重複要素を削除する

投稿日:

最終更新日:2016年09月14日

アイキャッチ

こんにちは。「Javaを復習する初心者」です。

int型配列に重複するする要素がある場合、その配列から重複をなくした配列を作るということをやりました。今回は自作のメソッドとStream-APIを使った方法を扱いました。

実験内容

サイズが20のint型配列にランダムに1から5の数値が格納されているとします。(サイズが20、ランダムに1から5という数字は適当に選んだ数字です。)この配列から重複する値を除いたもの配列を作ることを考えます。また、要素の順番も考慮します。

メソッドを作る

自前のメソッドをArrayListを使って処理を書いてみました。以下は仮引数int型配列numから新しい配列newNumsを作るフローです。

  1. List<Integer>型変数listにArrayListのインスタンスを格納する。
  2. 配列numsの各要素numに対して、以下を繰り返す。
    1. listにnumが含まれない場合、listにnumを追加する。
  3. listのサイズと同じサイズのint型配列newNumsを定義する。
  4. 繰り返しカウンタiが0からnewNumsのサイズ未満まで以下を繰り返す。
    1. newNums[i]にlistのi番目を格納する。
  5. newNumsを返却する。

ListにtoArray()メソッドがあるのですが、Integer型の配列のため、使うのをやめました。Streamを使った方法がプリミティブ型の配列を返すので、そちらに合わせました。

以下は上記をプログラミング例です。

ソース

    private static int[] test1(int[] nums) {

        List<Integer> list = new ArrayList<>();
        for (int num : nums) {
            if (!list.contains(num)) {
                list.add(num);
            }
        }

        int[] newNums = new int[list.size()];
        for (int i = 0; i < newNums.length; i++) {
            newNums[i] = list.get(i);
        }

        return newNums;
    }

if文の箇所についてですが、List型にcontainsメソッドが用意されていて、要素を含むかどうかを取得することができます。

streamを使った方法

もうひとつstreamを使った方法があります。以下です。

ソース

    private static int[] test2(int[] nums) {
        return Arrays.stream(nums).distinct().toArray();
    }

Arrays#stream(int[] array) メソッドでIntStreamが取得できます。distinct()というメソッドが用意されていて、重複を除いた要素から構成されるストリームを得ることができます。最後にtoArray()メソッドでint型の配列を取得しています。

速さ比較

どちらが速いか、以下のソースで比べました。それぞれのメソッドを30000回繰り返したときにかかった時間を計測しています。

ソース

        int[] nums = new int[20];

        Random random = new Random();
        for (int i = 0; i < nums.length; i++) {
            nums[i] = random.nextInt(5) + 1;
        }

        long start, end;

        start = System.currentTimeMillis();
        for (int i = 0; i < 30000; i++) {
            test1(nums);
        }
        end = System.currentTimeMillis();
        System.out.println("test1: " + (end - start));

        end = System.currentTimeMillis();
        for (int i = 0; i < 30000; i++) {
            test2(nums);
        }
        end = System.currentTimeMillis();
        System.out.println("test2: " + (end - start));

        System.out.println("確認");
        System.out.println("nums: " + Arrays.toString(nums));
        System.out.println("test1: " + Arrays.toString(test1(nums)));
        System.out.println("test2: " + Arrays.toString(test2(nums)));

結果

test1: 45
test2: 370
確認
nums: [4, 4, 4, 2, 3, 4, 3, 3, 1, 5, 2, 3, 5, 5, 1, 5, 2, 2, 3, 5]
test1: [4, 2, 3, 1, 5]
test2: [4, 2, 3, 1, 5]

自前のメソッドの方が速いという結果になりました。