配列の基本(Java)
同じ型の値を連続して管理するデータ構造です。『Java』の配列は宣言時に長さが固定され、後から変更できません。インデックスは0から始まり、『.length』で要素数を取得できます。1次元・多次元配列の宣言と初期化、要素アクセス、『Arrays.toString()』による文字列化、そして可変長が必要な場合の『ArrayList』との使い分けを解説します。
構文
import java.util.Arrays;
// 1次元配列の宣言と初期化(new で長さを指定する方法)です
型名[] 変数名 = new 型名[要素数];
// 1次元配列の宣言と初期化(初期値を直接並べる方法)です
型名[] 変数名 = {値0, 値1, 値2, ...};
// インデックスで要素にアクセスします(インデックスは0始まり)
変数名[インデックス]
// 配列の長さを取得します
変数名.length
// Arrays.toString() で配列を文字列化します(デバッグ・出力に便利)
Arrays.toString(変数名)
// 2次元配列の宣言と初期化です
型名[][] 変数名 = new 型名[行数][列数];
// 2次元配列を初期値付きで宣言します
型名[][] 変数名 = {
{値, 値, ...},
{値, 値, ...},
};
// 2次元配列を文字列化します
Arrays.deepToString(変数名)
配列の基本的な性質
| 性質 | 説明 |
|---|---|
| 固定長 | 宣言時に長さが決まり、後から要素数を変更できません。 |
| 0始まりインデックス | 最初の要素は『[0]』、最後の要素は『[length - 1]』でアクセスします。 |
| デフォルト値 | 『new』で確保した要素はデフォルト値(『int』なら『0』、『String』なら『null』)で初期化されます。 |
| 参照型 | 配列変数はオブジェクトへの参照です。『==』は内容ではなく参照を比較します。内容比較には『Arrays.equals()』を使います。 |
| 多次元配列 | 配列の配列として実現します。『int[][]』は「int配列の配列」です。 |
サンプルコード
ArrayBasic.java
import java.util.Arrays;
public class ArrayBasic {
public static void main(String[] args) {
// --- 配列の宣言と初期化(new で長さを指定)---
// まず長さ4の配列を確保します。各要素はデフォルト値(null)で初期化されます
String[] fighters = new String[4];
// インデックスを指定して要素を代入します。インデックスは0から始まります
fighters[0] = "草薙京"; // KOFの主人公です
fighters[1] = "八神庵";
fighters[2] = "テリー・ボガード";
fighters[3] = "不知火舞";
// 配列の長さは .length で取得します
System.out.println("ファイター数: " + fighters.length); // 4
// インデックスで要素にアクセスします
System.out.println("主人公: " + fighters[0]); // 草薙京
System.out.println("ライバル: " + fighters[1]); // 八神庵
// Arrays.toString() で配列全体を文字列として出力します
System.out.println("全ファイター: " + Arrays.toString(fighters));
// --- 配列の宣言と初期化(初期値を直接並べる方法)---
// より短く書けるリテラル初期化です
int[] power = {1800, 1600, 1500, 1400};
System.out.println("草薙京の戦闘力: " + power[0]); // 1800
// --- for文で全要素を順に処理 ---
System.out.println("=== 戦闘力一覧 ===");
for (int i = 0; i < fighters.length; i++) {
System.out.println(fighters[i] + ": " + power[i]);
}
// --- 拡張for文(for-each)で全要素を処理 ---
// インデックスが不要な場合はこちらがシンプルです
System.out.println("=== 参戦メンバー(for-each)===");
for (String name : fighters) {
System.out.println("・" + name);
}
// --- 範囲外アクセスはArrayIndexOutOfBoundsException になる ---
// fighters[4] にアクセスすると実行時例外が発生します
// 最後の要素は fighters[fighters.length - 1] でアクセスします
System.out.println("最後のファイター: " + fighters[fighters.length - 1]);
}
}
javac ArrayBasic.java java ArrayBasic ファイター数: 4 主人公: 草薙京 ライバル: 八神庵 全ファイター: [草薙京, 八神庵, テリー・ボガード, 不知火舞] 草薙京の戦闘力: 1800 === 戦闘力一覧 === 草薙京: 1800 八神庵: 1600 テリー・ボガード: 1500 不知火舞: 1400 === 参戦メンバー(for-each)=== ・草薙京 ・八神庵 ・テリー・ボガード ・不知火舞 最後のファイター: 不知火舞
ArrayMultiDim.java
import java.util.Arrays;
public class ArrayMultiDim {
public static void main(String[] args) {
// --- 2次元配列の宣言と初期化 ---
// KOFのチーム戦をイメージした3チーム×3人の2次元配列です
String[][] teams = {
{"草薙京", "二階堂紅丸", "大門五郎"}, // チーム日本
{"テリー・ボガード", "アンディ・ボガード", "ジョー東"}, // チームボガード
{"八神庵", "マチュア", "バイス"}, // チームヤガミ
};
// 行数(チーム数)は teams.length で取得します
System.out.println("チーム数: " + teams.length); // 3
// 列数(各チームのメンバー数)は teams[行].length で取得します
System.out.println("チームメンバー数: " + teams[0].length); // 3
// [行][列] でアクセスします。どちらも0始まりです
System.out.println("チーム日本のリーダー: " + teams[0][0]); // 草薙京
System.out.println("チームボガード2番手: " + teams[1][1]); // アンディ・ボガード
// --- ネストしたfor文で全要素を出力 ---
System.out.println("=== チーム一覧 ===");
for (int i = 0; i < teams.length; i++) {
System.out.print("チーム" + (i + 1) + ": ");
for (int j = 0; j < teams[i].length; j++) {
System.out.print(teams[i][j]);
if (j < teams[i].length - 1) {
System.out.print(", ");
}
}
System.out.println();
}
// --- Arrays.deepToString() で2次元配列を一括出力 ---
// Arrays.toString() では内側の配列がオブジェクト参照として表示されてしまいます
// 多次元配列には必ず deepToString() を使ってください
System.out.println("全チーム(deepToString): " + Arrays.deepToString(teams));
// --- 2次元配列の要素を変更 ---
teams[2][0] = "八神庵(怒り爆発)";
System.out.println("変更後: " + teams[2][0]);
}
}
javac ArrayMultiDim.java java ArrayMultiDim チーム数: 3 チームメンバー数: 3 チーム日本のリーダー: 草薙京 チームボガード2番手: アンディ・ボガード === チーム一覧 === チーム1: 草薙京, 二階堂紅丸, 大門五郎 チーム2: テリー・ボガード, アンディ・ボガード, ジョー東 チーム3: 八神庵, マチュア, バイス 全チーム(deepToString): [[草薙京, 二階堂紅丸, 大門五郎], [テリー・ボガード, アンディ・ボガード, ジョー東], [八神庵, マチュア, バイス]] 変更後: 八神庵(怒り爆発)
ArrayVsArrayList.java
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayVsArrayList {
public static void main(String[] args) {
// --- 配列(Array): 長さ固定 ---
// KOFの参戦ファイターを配列で管理します
// 宣言時に長さを決め、後から変更できません
String[] entryArray = {"草薙京", "八神庵", "テリー・ボガード"};
System.out.println("配列の長さ: " + entryArray.length);
System.out.println("配列の内容: " + Arrays.toString(entryArray));
// 要素の上書きはできますが、要素の追加・削除はできません
entryArray[0] = "クーラ・ダイアモンド"; // 上書きはOKです
System.out.println("上書き後: " + Arrays.toString(entryArray));
// entryArray[3] = "K'"; // インデックスが範囲外なのでArrayIndexOutOfBoundsExceptionが発生します
// --- ArrayList: 長さ可変 ---
// 要素の追加・削除が必要な場合は ArrayList を使います
ArrayList<String> entryList = new ArrayList<>();
entryList.add("草薙京");
entryList.add("八神庵");
entryList.add("テリー・ボガード");
System.out.println("リストの要素数: " + entryList.size()); // .length ではなく .size() です
System.out.println("リストの内容: " + entryList);
// add() で末尾に要素を追加できます(配列にはない機能です)
entryList.add("K'");
entryList.add("クーラ・ダイアモンド");
System.out.println("追加後: " + entryList);
// remove() でインデックス指定の要素を削除できます
entryList.remove(1); // インデックス1の要素(八神庵)を削除します
System.out.println("削除後: " + entryList);
// --- 配列 ↔ ArrayList の変換 ---
// 配列 → ArrayList
String[] arr = {"草薙京", "テリー・ボガード", "不知火舞"};
ArrayList<String> fromArr = new ArrayList<>(Arrays.asList(arr));
fromArr.add("ライデン"); // 要素を追加できるようになります
System.out.println("配列から変換したリスト: " + fromArr);
// ArrayList → 配列
String[] backToArr = fromArr.toArray(new String[0]);
System.out.println("リストから変換した配列: " + Arrays.toString(backToArr));
}
}
javac ArrayVsArrayList.java java ArrayVsArrayList 配列の長さ: 3 配列の内容: [草薙京, 八神庵, テリー・ボガード] 上書き後: [クーラ・ダイアモンド, 八神庵, テリー・ボガード] リストの要素数: 3 リストの内容: [草薙京, 八神庵, テリー・ボガード] 追加後: [草薙京, 八神庵, テリー・ボガード, K', クーラ・ダイアモンド] 削除後: [草薙京, テリー・ボガード, K', クーラ・ダイアモンド] 配列から変換したリスト: [草薙京, テリー・ボガード, 不知火舞, ライデン] リストから変換した配列: [草薙京, テリー・ボガード, 不知火舞, ライデン]
配列と ArrayList の使い分け
| 配列(Array) | ArrayList | |
|---|---|---|
| 長さ | 固定(変更不可) | 可変(追加・削除できる) |
| 要素数の取得 | .length | .size() |
| 要素の取得 | arr[i] | list.get(i) |
| 要素の追加 | 不可(上書きのみ) | list.add(値) |
| 要素の削除 | 不可 | list.remove(インデックス) |
| プリミティブ型の直接格納 | 可(『int[]』など) | 不可(『Integer』などラッパー型が必要) |
| 文字列化 | Arrays.toString(arr) | 『list.toString()』または『System.out.println(list)』 |
| 向いている用途 | 要素数が決まっている固定データ | 要素数が動的に変わるデータ |
よくあるミス1: ArrayIndexOutOfBoundsException(範囲外アクセス)
配列のインデックスは 0 から始まり、最大値は『length - 1』です。『length』と同じ値のインデックスを使うと実行時に『ArrayIndexOutOfBoundsException』が発生します。
IndexErrorNg.java
public class IndexErrorNg {
public static void main(String[] args) {
String[] fighters = {"草薙京", "八神庵", "テリー・ボガード"};
// fighters.length は 3 ですが、インデックス 3 は存在しません
// 最後の要素は fighters[2](= fighters[length - 1])です
for (int i = 0; i <= fighters.length; i++) { // <= にしてしまうと範囲外
System.out.println(fighters[i]);
}
}
}
javac IndexErrorNg.java java IndexErrorNg 草薙京 八神庵 テリー・ボガード Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 at IndexErrorNg.main(IndexErrorNg.java:8)
終了条件を『i <= fighters.length』から『i < fighters.length』に修正します。
IndexErrorOk.java
public class IndexErrorOk {
public static void main(String[] args) {
String[] fighters = {"草薙京", "八神庵", "テリー・ボガード"};
// < fighters.length にすることで、インデックス 0〜2 の範囲に収まります
for (int i = 0; i < fighters.length; i++) {
System.out.println(fighters[i]);
}
}
}
javac IndexErrorOk.java java IndexErrorOk 草薙京 八神庵 テリー・ボガード
よくあるミス2: length() と length の混同
『String』クラスの文字数取得は『length()』(メソッド呼び出し・括弧あり)ですが、配列の要素数取得は『.length』(フィールド参照・括弧なし)です。括弧の有無を間違えるとコンパイルエラーになります。
LengthConfusionNg.java
public class LengthConfusionNg {
public static void main(String[] args) {
String[] fighters = {"草薙京", "八神庵", "テリー・ボガード"};
// 配列に length() は存在しません(コンパイルエラー)
System.out.println(fighters.length()); // NG: cannot find symbol
}
}
javac LengthConfusionNg.java
LengthConfusionNg.java:6: error: cannot find symbol
System.out.println(fighters.length());
^
symbol: method length()
location: variable fighters of type String[]
1 error
配列には括弧なしの『.length』を使います。『String』の文字数には『.length()』(括弧あり)を使います。
LengthConfusionOk.java
public class LengthConfusionOk {
public static void main(String[] args) {
String[] fighters = {"草薙京", "八神庵", "テリー・ボガード"};
String name = "草薙京";
System.out.println("配列の要素数: " + fighters.length); // フィールド(括弧なし)
System.out.println("文字列の文字数: " + name.length()); // メソッド(括弧あり)
}
}
javac LengthConfusionOk.java java LengthConfusionOk 配列の要素数: 3 文字列の文字数: 3
よくあるミス3: == で配列の内容を比較してしまう
配列変数は参照(オブジェクトのアドレス)を保持しています。『==』で比較すると内容ではなく参照先が同じかどうかを確認するため、同じ内容の配列でも『false』になります。内容を比較するには『Arrays.equals()』を使います。
ArrayEqualNg.java
import java.util.Arrays;
public class ArrayEqualNg {
public static void main(String[] args) {
String[] a = {"草薙京", "八神庵"};
String[] b = {"草薙京", "八神庵"};
// == は参照を比較するため、内容が同じでも false になります
System.out.println(a == b); // false(別々のオブジェクト)
}
}
javac ArrayEqualNg.java java ArrayEqualNg false
配列の内容を比較するには『Arrays.equals()』を使います。
ArrayEqualOk.java
import java.util.Arrays;
public class ArrayEqualOk {
public static void main(String[] args) {
String[] a = {"草薙京", "八神庵"};
String[] b = {"草薙京", "八神庵"};
System.out.println(a == b); // false(参照が異なる)
System.out.println(Arrays.equals(a, b)); // true(内容が等しい)
}
}
javac ArrayEqualOk.java java ArrayEqualOk false true
概要
配列は同じ型の値を連続したメモリ領域に格納するデータ構造です。インデックスによるアクセスが高速で、要素数が決まっているデータの管理に適しています。長さは宣言時に確定し、後から変更できません。
要素数を確認するには『.length』を使います。『length()』(括弧あり)は『String』クラスのメソッドです。配列では『.length』(括弧なし・フィールド)を使います。また、存在しないインデックスにアクセスすると実行時に『ArrayIndexOutOfBoundsException』が発生します。ループの終了条件は『i < arr.length』(『i <= arr.length - 1』と等価)にするのが一般的です。
多次元配列の内容を出力するには『Arrays.deepToString()』を使います。『Arrays.toString()』を多次元配列に使うと、内側の配列がオブジェクト参照(『[Ljava.lang.String;@...』のような文字列)として表示されてしまいます。
要素の追加や削除が必要な場合は『ArrayList』が選択肢になります。『ArrayList』の使い方は『ArrayList の add() / get()』で確認できます。また、配列のソートや内容比較については『Arrays.sort()』『Arrays.equals() / toString()』も参考になります。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。