Java 入門

Java 配列要素へのアクセス

Java において、配列要素へのアクセスは最も基礎的な操作の一つです。これを通じて、配列の特定の場所に格納されている値をリテリブ(取得)したり、変更したりすることができます。

1. 配列インデックスの理解

Java では、配列内の各要素には一意のインデックス(Index)が割り当てられています。これらのインデックスは整数値であり、$0$ から始まり、配列の長さマイナス 1 まで続きます。したがって、長さ $n$ の配列の場合、インデックスの範囲は $0$ から $n-1$ となります。この「ゼロオリジン(0から始まる)」のカウント方式は、多くのプログラミング言語で一般的です。

  • 最初の要素: 常にインデックス $0$ に位置します。
  • 最後の要素: 常にインデックス(配列の長さ - 1)に位置します。
  • 境界外アクセス: 有効な範囲(0 から n - 1)以外のインデックスにアクセスしようとすると、ArrayIndexOutOfBoundsException が発生します。これは、その配列に属していないメモリ位置にアクセスしようとしていることを示すランタイムエラーであり、プログラムが強制終了する原因となります。

例:
例えば、長さ 5 の int 型配列 numbers があるとします。この配列の有効なインデックスは 0, 1, 2, 3, 4 です。

インデックス01234
1020304050

numbers[0] にアクセスすると値 10 が得られ、numbers[4] にアクセスすると値 50 が得られます。一方で、numbers[5] にアクセスしようとすると、インデックス 5 は有効範囲を超えているため、ArrayIndexOutOfBoundsException がスローされます。

2. 配列要素へのアクセス

配列内の要素にアクセスするには、配列名の後に角括弧 [] で囲んだインデックスを使用します。

構文:

配列名[インデックス]

2.1 要素の読み取り

特定のインデックスにある値を取得するには、以下の構文を使用します。

int value = numbers[2]; // インデックス 2 の値(すなわち 30)を変数 'value' に代入

2.2 要素の変更

特定のインデックスにある値を書き換えるには、代入演算子 = を使用します。

numbers[1] = 25; // インデックス 1 の値を 20 から 25 に変更

3. 完全なコード例

以下のコードは、配列の宣言、アクセス、変更、および配列の長さの取得方法をデモンストレーションしたものです。

public class ArrayAccess {
    public static void main(String[] args) {
        // 整数配列を宣言して初期化
        int[] numbers = {10, 20, 30, 40, 50};

        // 要素へのアクセス
        System.out.println("インデックス 0 の要素: " + numbers[0]); // 出力: 10
        System.out.println("インデックス 2 の要素: " + numbers[2]); // 出力: 30
        System.out.println("インデックス 4 の要素: " + numbers[4]); // 出力: 50

        // 要素の変更
        numbers[1] = 25;
        System.out.println("変更後のインデックス 1 の要素: " + numbers[1]); // 出力: 25

        // 配列の長さを取得する例
        int arrayLength = numbers.length;
        System.out.println("配列の長さは: " + arrayLength); // 出力: 5

        // length プロパティを使用して最後の要素にアクセス
        System.out.println("配列の最後の要素: " + numbers[arrayLength - 1]); // 出力: 50
    }
}

4. 配列のイテレーション(走査)

配列を扱う際、よくあるタスクの一つが全要素を走査(イテレート)することです。これは for ループや while ループを使用して実現できます。

4.1 標準的な for ループの使用

for ループは、あらかじめ要素の数がわかっている配列の走査に非常に適しています。

public class ArrayIteration {
    public static void main(String[] args) {
        int[] scores = {85, 90, 78, 92, 88};

        // for ループを使用して配列を走査
        System.out.println("スコアリスト:");
        for (int i = 0; i < scores.length; i++) {
            System.out.println("インデックス " + i + " のスコア: " + scores[i]);
        }
    }
}

この例では、ループカウンター i を 0 で初期化します。i が配列の長さより小さい限りループが継続され、毎回のイテレーションで scores[i] の値を出力し、i を 1 ずつ増加させます。

4.2 拡張 for 文(for-each)

Java は、インデックスを明示的に処理することなく配列やコレクションを走査できる、より簡潔な「拡張 for 文(enhanced for loop)」を提供しています。

public class EnhancedForLoop {
    public static void main(String[] args) {
        String[] names = {"アリス", "ボブ", "チャーリー", "デイビッド"};

        // 拡張 for 文を使用して配列を走査
        System.out.println("名前リスト:");
        for (String name : names) {
            System.out.println("名前: " + name);
        }
    }
}

この書き方は非常に可読性が高いのが特徴です。ループの各ステップで、現在の要素が自動的に変数 name に代入されます。

4.3 ループの選択基準

  • 標準的な for ループ: インデックスを使用する必要がある場合(例:ランキングの出力、インデックスに基づいた特定の値の変更など)や、配列の内容を直接変更する場合に使用します。
  • 拡張 for 文: インデックス情報が不要で、単に配列内の各要素を順番に読み取って処理したい場合に優先して使用します。コードがよりシンプルになります。

5. ArrayIndexOutOfBoundsException への対処

インデックスエラーによるプログラムのクラッシュを防ぐためには、インデックスが有効な範囲($0$ から length - 1)にあることを確認することが極めて重要です。

public class ArrayIndexOutOfBounds {
    public static void main(String[] args) {
        int[] values = {100, 200, 300};

        // この行は ArrayIndexOutOfBoundsException を引き起こします(インデックス 3 は存在しないため)
        // System.out.println(values[3]);

        // 安全なアクセス:事前にチェックを行う
        int index = 3;
        if (index >= 0 && index < values.length) {
            System.out.println("インデックス " + index + " の値: " + values[index]);
        } else {
            System.out.println("エラー:インデックス " + index + " は範囲外です。");
        }
    }
}

6. 実践的な例

6.1 配列要素の平均値を計算する

public class ArrayAverage {
    public static void main(String[] args) {
        double[] numbers = {5.5, 7.2, 9.1, 6.8, 8.3};
        double sum = 0;
        for (double number : numbers) {
            sum += number;
        }
        double average = sum / numbers.length;
        System.out.println("平均値は: " + average);
    }
}

6.2 配列内の最大値を探す

public class ArrayMax {
    public static void main(String[] args) {
        int[] values = {45, 12, 89, 56, 23};
        int max = values[0]; // 最初の要素を最大値と仮定
        for (int i = 1; i < values.length; i++) {
            if (values[i] > max) {
                max = values[i]; // より大きな値が見つかった場合、max を更新
            }
        }
        System.out.println("最大値は: " + max);
    }
}

6.3 配列の反転(リバース)

public class ArrayReverse {
    public static void main(String[] args) {
        int[] original = {1, 2, 3, 4, 5};
        int[] reversed = new int[original.length];
        
        for (int i = 0; i < original.length; i++) {
            // 元の配列の値を後ろから順番に新しい配列へ格納
            reversed[original.length - 1 - i] = original[i];
        }

        System.out.println("元の配列:");
        for (int value : original) {
            System.out.print(value + " ");
        }

        System.out.println("\n反転後の配列:");
        for (int value : reversed) {
            System.out.print(value + " ");
        }
    }
}