【Java】Arraysクラスの便利メソッド紹介

2022-06-14

Arrays.setAllとかいう便利なメソッドを見つけたけど、日本語文献があまり見当らなかったので久しぶりに記事書く。

ついでにArraysクラスに用意されてる他の便利メソッドも一緒に紹介します。

setAll

好きな規則性に従って配列の各要素に値を設定できるやつ。

とりあえず例を見てもらった方が分かりやすいと思う。

使用例1
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] array = new int[10];
        Arrays.setAll(array, i -> i * 2);

        System.out.println(Arrays.toString(array));
    }
}
実行結果1
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

ここで、setAll()メソッドの第2引数として与えられているのはジェネレータ関数というもの。

この場合、i0からarray.length-1までの値をとります。

つまりfor(int i=0; i<array.length; i++)と同義
もちろん、->の前で定義してるループ変数名iは別にjでもaでもunkoでもいい。

ちなみに、このメソッドはint型以外に対しても使える

使用例2
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Object[] array = new Object[10];
        Arrays.setAll(array, i -> (char) ('a' + i));

        System.out.println(Arrays.toString(array));
    }
}

実行結果2
[a, b, c, d, e, f, g, h, i, j]

char型用のsetAll()はないけどObject型で配列定義しとけばいけちゃうというね

copyOf

配列のコピーを作成するやつ。
代入演算子「=」のみで別の変数に代入してもコピーとはならず、参照となるので。
(別の変数名から同じオブジェクトにアクセスすることになる)

つまり、同じ要素からなる新たな配列を用意したい場合には、このArrays.copyOf()メソッドを用いることになる。

(これは便利とかいう話でなく、配列を扱う上で知っておくべきことかもしれない……)

使用例
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        // コピー元配列
        int[] array = {1, 2, 3};

        // 配列の参照
        int[] refArray = array;

        // 配列のコピー
        int[] copyArray = Arrays.copyOf(array, array.length);

        System.out.println("--- 変更前 ---");
        System.out.println("コピー元: " + Arrays.toString(array));
        System.out.println(" 参照元: " + Arrays.toString(refArray));
        System.out.println("コピー先: " + Arrays.toString(copyArray));

        // 参照型の配列の先頭を0に変更
        refArray[0] = 0;

        // コピー先配列の先頭を-1に変更
        copyArray[0] = -1;

        System.out.println("--- 変更後 ---");
        System.out.println("コピー元: " + Arrays.toString(array));
        System.out.println(" 参照元: " + Arrays.toString(refArray));
        System.out.println("コピー先: " + Arrays.toString(copyArray));
    }
}
実行結果
--- 変更前 ---
コピー元: [1, 2, 3]
参照元: [1, 2, 3]
コピー先: [1, 2, 3]
--- 変更後 ---
コピー元: [0, 2, 3]
参照元: [0, 2, 3]
コピー先: [-1, 2, 3]

copyOfRange

copyOf()メソッドの機能追加版みたいなやつ。
コピー元配列の好きな範囲の要素だけ持ってこれる。

使用例
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] array = {1,2,3,4,5};

        // 2要素目から最後尾の要素+1をコピーした配列を作成
        int[] copyArray = Arrays.copyOfRange(array, 1, array.length + 1);
        System.out.println(Arrays.toString(copyArray));
    }
}

さりげなく範囲外まで指定してみる。

実行結果
[2, 3, 4, 5, 0]

なんと動く。

このような場合には、指定された長さになるよう0埋めしてくれるらしい。

実はこれcopyOfでもできるってよ。

fill

配列の全要素を好きな値で初期化できるやつ。

使用例
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        // int型の配列
        int[] intArray = new int[5];
        // 全要素を 1 で初期化
        Arrays.fill(intArray, 1);
        System.out.println(Arrays.toString(intArray));

        // Stringでもできるよ
        String[] stringArray = new String[5];
        Arrays.fill(stringArray, "abc");
        System.out.println(Arrays.toString(stringArray));
    }
}
実行結果
[1, 1, 1, 1, 1]
[abc, abc, abc, abc, abc]

sort

名前の通り、配列をソートしてくれるやつ。
ただし昇順

ちなみに、Comparator.reverseOrder()というものを第2引数に追加すると降順ソートになる。

使用例
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Integer[] array = {0, 2, 4, 3, 1};

        System.out.print("ソート前 :");
        System.out.println(Arrays.toString(array));

        Arrays.sort(array);
        System.out.print("昇順ソート後:");
        System.out.println(Arrays.toString(array));

        Arrays.sort(array, Comparator.reverseOrder());
        System.out.print("降順ソート後:");
        System.out.println(Arrays.toString(array));
    }
}
実行結果
ソート前 :[0, 2, 4, 3, 1]
昇順ソート後:[0, 1, 2, 3, 4]
降順ソート後:[4, 3, 2, 1, 0]

注意点として、reverseOrder()を使う場合は、ソート対象配列はint型でなくInteger型にしておく必要がある。

ちなみにComparator.reverseOrder()Collections.reverseOrder()どっち使っても降順ソートできる。

違いは知らん

binarySearch

バイナリサーチ(二分探索) とは:ソート済み配列から効率的に要素を検索するアルゴリズムのこと。

どんなアルゴリズムなのか、年齢当てゲームで例を示すと、

質問1「50歳以下か」→◯
質問2「25歳以下か」→◯
質問3「13歳以下か」→✕
質問4「19歳以下か」→✕
質問5「22歳以下か」→◯
質問6「21歳以下か」→◯
質問7「20歳以下か」→◯
答え:20歳

という感じ(厳密にはちょっと違うけど)。

つまりは、ソート済みであることを利用して探索範囲を半分ずつ減らしてく探索方法。

使用例
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] array = new int[10];

        // 1~10の値を代入
        Arrays.setAll(array, i -> i + 1);
        System.out.println(Arrays.toString(array));

        // 検索ターゲット
        int target = 2;
        // 検索→位置を取得
        int position = Arrays.binarySearch(array, 2);

        System.out.println(target + "は第[" + position + "]要素にあります");
    }
}
実行結果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
2は第[1]要素にあります

stream

ストリームってなに
→ 本来for文などの反復処理を記述する必要があったものを、メソッドチェーンで簡潔に記述できるもの(クソ雑説明)

Arraysクラスの一メソッドとして紹介するには奥が深すぎるとこなので、
ここでの説明は割愛させてください……

Stream APIの概要は以下の記事を読んでみてくだしあ

とても分かりやすかった

おわりに

Arraysクラス完全に理解した

スポンサーリンク