Javaの配列と多次元配列をマスター!初期化パターン(静的・動的)徹底解説ガイド
生徒
「Javaでたくさんのデータをまとめて管理したいとき、変数を何個も作るのは大変ですよね。何か良い方法はありますか?」
先生
「そんなときこそ配列の出番です。配列を使えば、同じ種類のデータを一つのグループとして効率よく扱うことができますよ。」
生徒
「配列を作るには、最初に何を準備すればいいんでしょうか?初期化という言葉を聞いたことがあるのですが……」
先生
「初期化には、あらかじめ入れる値が決まっている場合と、後から値を入れる場所だけ作る場合の二通りがあります。これから詳しく見ていきましょう!」
1. Javaの配列とは?基本概念を整理しよう
Javaプログラミングにおいて、配列は非常に重要な役割を果たします。配列とは、同じデータ型の値を複数まとめて格納できる箱のようなものです。通常、一つの変数には一つの値しか保存できませんが、配列を利用することで、出席番号順の生徒の名前や、一週間の気温データ、試験の点数一覧などを一括で管理できるようになります。
配列内の各データは「要素」と呼ばれ、それぞれの要素には「インデックス(添え字)」という番号が割り振られます。この番号は必ず「0」から始まるのがJavaのルールです。例えば、5つの要素を持つ配列であれば、インデックスは0、1、2、3、4となります。初心者が最も間違えやすいのが、1番目の要素のインデックスを1だと思い込んでしまうことですので、注意しましょう。
配列を使用する大きなメリットは、繰り返し処理との相性が抜群に良いことです。for文やwhile文といったループ処理を組み合わせることで、数百、数千という膨大なデータに対しても、わずか数行のコードで一括処理が可能になります。データの集まりを効率的に操作することは、アプリケーション開発の根幹と言えるでしょう。
2. 静的初期化:決まった値を最初から入れる方法
配列を作成する際、すでに中身に入れる具体的なデータが決まっている場合には「静的初期化」という手法を使います。これは、配列の宣言と同時に値を代入する方法で、コードが非常にシンプルに書けるのが特徴です。
静的初期化では、中身のデータの個数に合わせて、Javaが自動的に配列のサイズを決定してくれます。そのため、自分で「この配列の長さは5です」と指定する必要はありません。定義した瞬間に、指定した値が順番に各要素へ格納されます。
public class StaticArrayExample {
public static void main(String[] args) {
// 静的初期化のパターン1
int[] scores = {80, 90, 75, 60, 100};
// 静的初期化のパターン2(new演算子を使う)
String[] colors = new String[]{"赤", "青", "緑"};
System.out.println("1番目の点数:" + scores[0]);
System.out.println("2番目の色:" + colors[1]);
}
}
1番目の点数:80
2番目の色:青
上記の例では、点数を管理する配列と色を管理する配列を静的に初期化しています。波括弧を用いる記述方法は非常に直感的で分かりやすく、ソースコードの可読性を高める効果もあります。
3. 動的初期化:まずは場所(サイズ)だけ確保する方法
一方で、プログラムの実行中にユーザーが入力した値を入れたい場合や、後から計算結果を格納したい場合は、あらかじめ「箱の数」だけを決めておく「動的初期化」を使用します。この方法では、まずメモリ上に指定した要素数分の領域を確保し、後から好きなタイミングで値を代入していきます。
動的初期化の際は、newというキーワードを使って配列を生成します。このとき、配列の要素数は一度決めると後から変更することができません。もし要素数が5の配列を作った場合、その配列は生涯5つのデータしか保持できないのです。もし柔軟にサイズを変えたい場合は、JavaのコレクションフレームワークであるArrayListなどを検討することになりますが、まずは基本である配列の動的初期化を完璧に理解しましょう。
public class DynamicArrayExample {
public static void main(String[] args) {
// 要素数3のString型配列を動的に作成
String[] fruits = new String[3];
// 各要素に値を代入
fruits[0] = "リンゴ";
fruits[1] = "バナナ";
fruits[2] = "オレンジ";
for (int i = 0; i < fruits.length; i++) {
System.out.println(i + "番目の果物:" + fruits[i]);
}
}
}
0番目の果物:リンゴ
1番目の果物:バナナ
2番目の果物:オレンジ
4. 多次元配列の基本:行列のようなデータ構造
これまでは一つの列にデータが並ぶ「一次元配列」を見てきましたが、Javaには配列の中にさらに配列を入れる「多次元配列」という仕組みがあります。最もよく使われるのは、縦と横の広がりを持つ「二次元配列」です。これは数学の行列や、Excelのスプレッドシートのような表形式のデータを扱うのに最適です。
二次元配列を宣言する場合、角括弧を二つ並べてint[][] tableのように記述します。最初の括弧が「行(縦)」を、次の括弧が「列(横)」を表すと考えると理解しやすくなります。例えば、3名の生徒の5教科の点数を管理する場合、3行5列の二次元配列を作れば、一人一人の成績を整理して保持することができます。
多次元配列も一次元配列と同様に、静的初期化と動的初期化のどちらも可能です。ネスト(入れ子)構造になるため、記述が少し複雑に見えますが、構造を落ち着いて把握すれば難しいことはありません。
5. 二次元配列の静的初期化と動的初期化の実装
具体的に、二次元配列をどのようにコードで表現するかを見ていきましょう。静的初期化では、外側の波括弧の中に、さらに内側の波括弧を並べて記述します。これにより、表全体のデータを一度に定義できます。動的初期化の場合は、行数と列数をそれぞれ指定して領域を確保します。
public class MultiArrayExample {
public static void main(String[] args) {
// 二次元配列の静的初期化(2行3列)
int[][] matrix = {
{10, 20, 30},
{40, 50, 60}
};
// 二次元配列の動的初期化(3行2列)
String[][] seats = new String[3][2];
seats[0][0] = "佐藤";
seats[0][1] = "鈴木";
seats[1][0] = "高橋";
seats[1][1] = "田中";
seats[2][0] = "伊藤";
seats[2][1] = "渡辺";
System.out.println("行列の1行2列目:" + matrix[0][1]);
System.out.println("座席の3行目1列目:" + seats[2][0]);
}
}
行列の1行2列目:20
座席の3行目1列目:伊藤
二次元配列を扱う際は、二重のfor文(ネストしたループ)を使用することが一般的です。外側のループで行を回し、内側のループで列を回すことで、表の全データを順番に取り出すことが可能になります。この処理パターンはアルゴリズムの基礎としても非常に頻出するため、必ずマスターしておきたいポイントです。
6. 配列を扱う上での重要な注意点と例外
配列の操作に慣れてくると必ず直面するのが、エラー(例外)への対応です。特に初心者が頻繁に遭遇するのが、ArrayIndexOutOfBoundsExceptionというエラーです。これは、配列の範囲外のインデックスにアクセスしようとしたときに発生します。
例えば、要素数が3の配列に対して、インデックス「3」を指定して値を読み書きしようとするとこのエラーになります。先述の通り、インデックスは0から始まるため、要素数3の場合は0から2までしか存在しないからです。また、配列は一度作成するとその長さを変更できないため、要素が足りなくなった場合は、より大きな配列を新しく作り直して、古いデータをコピーするという手順が必要になります。
さらに、配列の要素に初期値を代入せずに参照した場合、型に応じたデフォルト値が入っていることも覚えておきましょう。int型などの数値型であれば「0」、boolean型であれば「false」、String型などの参照型であれば「null」が自動的に入ります。この「null」が入っている状態で、その要素のメソッドを呼び出そうとするとNullPointerExceptionが発生するため、動的初期化の後は速やかに適切な値を代入する習慣をつけましょう。
7. 実践:多次元配列を使った複雑なデータ管理
最後に、より実戦に近い形で配列を活用する方法を考えてみましょう。例えば、RPGゲームのマップデータや、カレンダーの予定管理、画像データのピクセル情報などは、すべて多次元配列の応用で成り立っています。画像データであれば、各ピクセルのRGB情報を数値として二次元、あるいは三次元配列に格納して処理します。
また、Javaの多次元配列は「不規則配列」を作ることも可能です。これは、各行の列数が異なる配列のことで、Javaの配列が「配列の配列」であるという性質を利用しています。例えば、1組は3人、2組は5人といったクラスごとの生徒名簿を作る際に、メモリを無駄なく使うために行ごとに異なる列数を割り当てることができます。
public class AdvancedArrayExample {
public static void main(String[] args) {
// 各行の要素数が異なる不規則配列
int[][] irregularArray = new int[3][];
irregularArray[0] = new int[2]; // 0行目は2要素
irregularArray[1] = new int[4]; // 1行目は4要素
irregularArray[2] = new int[3]; // 2行目は3要素
// 値の代入と確認
irregularArray[1][3] = 999;
System.out.println("1行目の長さ:" + irregularArray[0].length);
System.out.println("2行目の長さ:" + irregularArray[1].length);
System.out.println("1行3列目の値:" + irregularArray[1][3]);
}
}
1行目の長さ:2
2行目の長さ:4
1行3列目の値:999
このように、Javaの配列は非常に柔軟であり、基礎を固めることで高度なデータ構造の構築が可能になります。静的初期化で手軽にデータを用意するか、動的初期化でシステム要件に合わせて領域を確保するか、状況に応じて最適な方法を選択できるようになりましょう。配列を自由に操れるようになれば、Javaエンジニアとしてのレベルは格段にアップします。何度もコードを書き、配列の挙動を肌で感じてみてください。