Javaの勉強を始めたけど、配列の使い方がよくわからない・・・
配列はどのような用途で使えばいいの?変数との違いはなに?
配列を効率よく覚えたいけど何か良い方法はないかな?
Javaの勉強を始めたばかりの初学者が、最初につまづきやすいのが配列と言えます。配列の基本は理解できても、実際の業務では配列を駆使してさまざまな処理を行う必要があります。
しかし、Javaの配列について基礎的な使い方から実務でよく使う実装方法を体系的に教えているサイトは少ないため、なんとなくしか理解できていない方も多いのではないでしょうか?
こんにちは!侍エンジニア編集部です。
この記事では実際にJavaエンジニアとしてWebサイトの構築、業務用アプリケーションでJavaを使用していた著者が「配列の基礎の基礎」「便利な使い方」「抑えておきたい配列のポイント」までを、わかりやすく解説いたします。
初心者必見の内容となりますので、ぜひ最後まで読んでいただいてJavaの配列について理解を深めていただければ幸いです。
この記事はこんな人のために書きました
- 配列の基礎の基礎を学びたい方
- 配列のさまざまな操作方法を知りたい方
- 配列でつまづいて困っている方
なお、Javaの記事については、こちらにまとめています。
Javaの配列とは
では、ここから早速Javaの配列について学習を進めていきましょう。
まずは配列のは何かを知るために、変数の使い方についておさらいしておきます。
// 変数を宣言 int score1, score2, score3, score4, score5; // 変数に値を格納 score1 = 50; score2 = 70; score3 = 40; score4 = 80; score5 = 55;
このプログラムでは生徒の得点をそれぞれの変数を定義して格納しています。しかし、もし生徒の数が30人、50人だったとしたら、生徒の人数分変数を定義しなくてはいけません。
そこで、配列を使えば同じ型のデータをまとめて格納できます。
ではこのプログラムを配列に置き換えてみましょう。
// 配列を宣言 int score[] = new int[5]; // 配列に値を格納 score[0] = 50; score[1] = 70; score[2] = 40; score[3] = 80; score[4] = 55;
このプログラムでは、配列変数score[]を宣言して、そのあと配列用の箱を5個分用意しています。変数の後ろに角括弧[]をつけることで、「これは配列の変数です」ということを宣言しています。
また、「new int[5]」の意味はわかりますでしょうか?
new演算子は実体、つまりインスタンスを作るために使用します。ここでの配列の場合は「int型の配列変数名で5個分の箱を確保します」ということを最初に宣言する必要があります。つまり配列のイメージを図にすると以下のようになります。
ここでは配列に5個分の箱を用意したから、0から順番に値を格納していることになります。score[0]のように0から始まる番号をインデックス(添字)または要素番号と言います。1からではなく0から始まるから注意しましょう。
配列は複数の値を1つの変数として扱えるデータ構造のことを指します。intならint型の配列を、StringならString型の値を複数扱えることができるので、同じ種類のデータをまとめて管理したいときに非常に便利です。
例えばここで紹介したように複数のテストの結果を扱いたい場合、配列を定義して人数分の箱を用意しておけばまとめて管理することが可能です。
配列とは
- 複数の値を1つの変数として扱えるデータ型のこと
- 同じデータ型の値を複数格納できる
- インデックス(添字)は0から始まる
Javaの配列を使うメリットって?
配列がどのようなものか、なんとなくイメージはできましたでしょうか?ここでは配列を使用することで得られる大きなメリットについて解説していきます。
配列の使い方はなんとなくわかったんですけど、プログラミングするときにどうやって使うのか?どんなときに使うのかがイメージできてない方も多いのではないでしょうか?
ここでは、配列を使うことでどんなメリットがあるのかを解説していきます。
大量のデータを扱える
配列は同じデータ型の値を複数扱うときに便利です。ちょっとしたシステムやアプリを開発する場合、さまざまな大量のデータを扱う必要が必ずと言っていいほどでてきます。たとえば、同じデータ型で値を1000個用意しなければ行けない場合、変数を1000個分用意する必要があります。
int 変数1,変数2,変数3,変数4,変数5,変数6,変数7,変数8,変数9,〜 変数1000;
このように変数を1000個分用意するなんてかなり面倒ですよね。しかし、配列なら一度の定義で1000個分の入れ物を用意するも可能なのです。
int 変数[] = new int[要素数];
同じような変数を複数用意する手間が省けて非常に便利ですね。
さまざまな配列関連のライブラリ、メンバが使える
配列は前述したように複数のデータを扱うことができますが、たくさんのデータがあるとその分配列に対してやらなければいけない処理が発生してしまいます。
たとえば「配列から必要な値だけ取り出したい」「配列Aと配列Bを結合したい」「配列の値を昇順・降順で並び替えたい」「この配列の要素数ってどれくらいだっけ?」など。そのような場合は配列で使用できるメンバやライブラリを使うことで簡単に解決することができます。
Javaの配列の基礎的な使い方
配列を使うには、通常の変数と同様に宣言を行う必要があります。
int score[];
変数名の後ろに角括弧[]をつけることで「この変数は配列ですよ」ということを宣言しています。これで配列の変数scoreを宣言しましたが、配列を使用するにはいくつ箱を用意するかを決める必要があります。
そのため、あらかじめ配列の要素数を指定する必要があります。
int score[]; score = new int[5];
以下のように宣言と初期化を一度に行うことも可能です。
int score[] = new int[5];
これで、配列の宣言と初期化を行うことができました。ここではint型の配列を宣言していますが、配列は初期化と同時に各要素数には0が入ります。また、配列の初期値が予め決まっている場合は、宣言と同時に値を代入することもできます。
int score[] = {50,70,40,80,55};
では、実際に配列の各要素に値を代入して正しく値が格納されているか確認してみましょう。
public class Main { public static void main(String[] args) throws Exception { // 変数の宣言と初期化 int score[] = {50,70,40,80,55}; // 値を出力 System.out.println(score[0]); System.out.println(score[1]); System.out.println(score[2]); System.out.println(score[3]); System.out.println(score[4]); } }
実行結果:
50 70 40 80 55
配列の各要素に代入した値が出力できていることがわかりますね。しかし、配列の値を出力するときに「score[0]、score[1] …」のように配列の各要素ごとにインデックス番号を指定するのは面倒です。
そのような場合の手段として、for文を使用して配列の要素数分繰り返し処理を実行する方法があります。
public class Main { public static void main(String[] args) throws Exception { // 変数の宣言と初期化 int score[] = {50,70,40,80,55}; // 値を出力 for(int i=0; i<5; i++){ System.out.println(score[i]); } } }
これで、プログラムを簡単に記述することができました。この処理のポイントとしては、for文で配列の要素数分繰り返し処理を実行し、変数iの値は初期値が0で繰り返し処理ごとに変数iがインクリメント(1ずつ加算)されます。
つまり、1回目の繰り返し処理でのiの値は0、2回目のiの値は1となるので配列scoreのインデックス番号にiを指定することで、配列の要素順に繰り返し処理が実行できます。Javaのfor文については、以下の記事でもわかりやすく解説していますので、ぜひ参考にしてくださいね。
基礎的な使い方まとめ
- 配列は「型名 変数名[] = new int[要素数];」で宣言と初期化ができる
- 初期値が決まっている場合は「型名 変数名[] = {値1,値2…}」も可能
- 配列の要素ごとに処理を行うにはfor文が便利
Javaの配列の便利な使い方
配列の要素数を取得してみよう
配列の処理を行うときに、配列の要素数をあらかじめ知っておきたい場合があります。たとえば、配列の要素数分処理を実行したいときに、配列の要素の数がわかっていれば何回繰り返し処理を実行すればよいかが明確になります。
配列の要素数は基礎的な使い方で説明したとおり、配列を作るときにあらかじめ箱の数を指定する必要があります。しかし配列を複数使う場合、いちいち配列の要素数を全部覚えておくのは面倒ですし、間違った要素数を指定して例外が発生する可能性もあります。
そこで配列の要素数を取得するには配列名の後ろに「length」を指定することで簡単に取得することができます。
要素数 = 配列変数名.length
実際に配列の要素数を取得してみましょう!
public class Main { public static void main(String[] args) throws Exception { int[] score = {50,70,40,80,55}; System.out.println(score.length); } }
実行結果:
5
このように簡単に取得できることがわかりますね。基礎的な使い方で紹介したプログラムも繰り返し処理の回数は直接指定していますが、lengthを使用することで正確に配列の要素数分繰り返し処理ができます。
public class Main { public static void main(String[] args) throws Exception { // 変数の宣言と初期化 int score[] = {50,70,40,80,55}; // 値を出力 for(int i=0; i<score.length; i++){ System.out.println(score[i]); } } }
実行結果:
50 70 40 80 55
配列の要素数を取得するには
- 配列の要素数は「変数名.length」で簡単に取得できる
- 配列の要素分繰り返し処理を行う場合はlength使用すると便利
配列に値を追加してみよう
配列は最初に要素数を決めてしまうため、あとから値の追加を行うことができません。そのため、方法としては値を追加するための配列を別途用意して、元の配列の値をコピーする必要があります。
配列をコピーするには、java.lang.Systemクラスの「arraycopy」メソッドを使用します。arraycopyメソッドを使用することで、配列のコピーが可能です。
System.arraycopy(コピー元の配列, コピー元配列の開始位置, コピー先の配列, コピー先配列の開始位置, コピー元配列の要素数);
以下のプログラムで確認してみましょう。
public class Main { public static void main(String[] args) throws Exception { //コピー元の配列 int[] score1 = {50,70,40,80,55}; //コピー先の配列 int[] score2 = new int[10]; //配列をコピー System.arraycopy(score1, 0, score2, 0, score1.length); for(int i=0; i<score2.length; i++){ System.out.println(score2[i]); } } }
実行結果
50 70 40 80 55 0 0 0 0 0
このプログラムでは、まず5個の要素を持つ配列score1を宣言して値を代入し、次に10個分の要素を持つ配列score2を宣言しています。arraycopyの処理ではコピー元の配列score1の内容をコピー先の配列score2にコピーしています。
score2の中身を確認すると、score1の内容がコピーされていることがわかりますね!
配列に値を追加するには
- java.lang.Systemクラスのarraycopyを使う
- 追加したい要素分の配列を作成する
- arraycopyを使用するとコピー元配列の値がコピー先配列にコピーされる
配列の値を検索してみよう
配列で大量のデータを扱っていると、配列の中に目的の値が格納されているか? チェックしたい場合があります。例えば、配列に”オレンジ”の値が含まれているか確認したい場合はどうすれば良いでしょうか?
<if文を使う方法>
配列の中で特定の値をチェックする場合、まずif文を使用する方法があります。次のプログラムを見てみましょう。
public class Main { public static void main(String[] args) throws Exception { // 配列を宣言 String fruits[] = {"りんご", "オレンジ", "メロン", "バナナ"}; // 配列の値を検索 for(int i=0; i<fruits.length; i++){ if(fruits[i] == "オレンジ"){ System.out.println("オレンジが見つかりました!"); } } } }
実行結果:
オレンジが見つかりました!
このようにfor文の繰り返し処理の中で、if文の条件式で”オレンジ”と一致する値がないかを配列の要素ごとに検索することで、簡単にチェックできます。if文については、以下の記事でもわかりやすく解説していますので、使い方がよくわからない方は合わせて参考にしてください!
<util.ArraysのasListを使う方法>
配列の中に特定の値を含まれるか簡単にチェックしたい場合はjava.util.Arraysクラスの「asList」メソッドを使うと便利です。次のプログラムを見てみましょう。
import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { // 配列を宣言 String fruits[] = {"りんご", "オレンジ", "メロン", "バナナ"}; // 配列の値を検索 if(Arrays.asList(fruits).contains("オレンジ")){ System.out.println("オレンジが見つかりました!"); } } }
実行結果:
オレンジが見つかりました!
ArraysクラスのasListは配列をリストに変換するためのメソッドです。asListメソッドは、引数で指定した値を検索して真偽値を返すcontainsメソッドが使えます。そのため、特定の値が含まれているかチェックしたいだけなら配列でも一旦リストに変換して簡単に判定できます。
配列の値を検索するには
- 配列の値を検索するには繰り返し処理中で各インデックスごとにif文で検索できる
- 特定の値が存在するか確認するにはjava.util.ArraysクラスのasListメソッドが便利
配列の順番を並び替えよう
配列の値を並び替える(ソート)には、java.util.Arraysクラスの「sort」メソッドを使用すると便利です。
Arrays.sort(配列名);
sortメソッドを使用することで、配列を昇順(値が小さい順)に並び替えることができます。次のプログラムを見てみましょう。
import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { // 配列を宣言 int score[] = {50,70,40,80,55}; // 配列のソート Arrays.sort(score); // 値を出力 for(int i=0; i<score.length; i++){ System.out.println(score[i]); } } }
実行結果:
40 50 55 70 80
String型の値も同様に並び替えができます。
import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { // 配列を宣言 String fruits[] = {"apple", "orange", "melon", "banana"}; // 配列のソート Arrays.sort(fruits); // 値を出力 for(int i=0; i<fruits.length; i++){ System.out.println(fruits[i]); } } }
実行結果:
apple banana melon orange
String型の文字列の場合はアルファベット順に並び替えられます。降順(値が大きい順)に並び替えたい場合は、sortメソッドの第二引数にjava.util.Collectionsクラスの「reverseOrder」メソッドも合わせて指定する必要があります。
Arrays.sort(配列名, Collections.reverseOrder());
次のプログラムで確認してみましょう。
import java.util.Arrays; import java.util.Collections; public class Main { public static void main(String[] args) throws Exception { // 配列を宣言 Integer score[] = {50,70,40,80,55}; // 配列のソート Arrays.sort(score, Collections.reverseOrder()); // 値を出力 for(int i=0; i<score.length; i++){ System.out.println(score[i]); } } }
実行結果:
80 70 55 50 40
配列の値が降順で並び替えできていることがわかりますね!
配列を並び替える(ソート)には
- 昇順で並び替えるならArrays.sort
- 降順で並び替えるならArrays.sortの引数にjava.util.CollectionsのreverseOrderを指定する
Javaの配列での気をつけておきたいポイント
要素数を超えて値を格納できない
配列は要素数を超えて新しい値を追加することができません。たとえば、以下のように5個分の要素がある配列を用意したとします。
int[] array = new int[5];
配列のインデックスは0から始めるので5個分の要素を作成したとき、インデックスは0,1,2,3,4になります。つまり、この配列に値を代入するときは、以下のようになります。
array[0] = 10; array[1] = 20; array[2] = 30; array[3] = 40; array[4] = 50;
しかし、ここで要素数を超えた配列のインデックスに値を代入しようとするとどうなるでしょうか?以下のプログラムで確認してみましょう。
public class Main { public static void main(String[] args) throws Exception { // 配列を宣言 int[] array = new int[5]; array[0] = 10; array[1] = 20; array[2] = 30; array[3] = 40; array[4] = 50; array[5] = 60; // 値を出力 for(int i=0; i<array.length; i++){ System.out.println(array[i]); } } }
実行結果:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5 at Main.main(Main.java:17)
「ArrayIndexOutOfBoundsException」は主に配列の存在しない要素を指定した場合に発生する例外です。今回は要素数を超えてarray[5] に値を代入しようとして発生しました。
配列ではこのように要素数を超えた配列にアクセスをしようとして例外が発生するパターンが非常に多いので注意が必要です。
配列の要素数は変更できない
配列は最初に要素数を決定するため、あとから要素数を変更することはできません。以下のように最初に配列の要素数を5で指定した場合は、その後の要素数はずっと5で固定されます。
int[] array = new int[5];
あとから要素数を増やす必要性が生じた場合は、「配列に値を追加してみよう」で紹介したようにarraycopyを使用する方法があります。しかし、値を追加するためにわざわざarraycopyで別の配列を用意するのは面倒ですし、配列の要素数が大きい場合はその分コピーするのにメモリを消費してしまいます。
そのため「要素数が決まっていない」「あとから値を追加する可能性がある」などの場合は固定長の配列ではなく、可変長のList(リスト)を使用したほうがいいでしょう。
そもそもリストとは
- List(リスト)は配列のように複数の値をまとめて扱うことがでる
- 配列と異なるところは、要素数を決めずに値を随時追加することができますので用途によって使い分ける
リストについては以下の記事で詳しく解説していますので、ぜひ参考にしてください。
配列は参照型変数
配列は参照型の変数です。参照型の変数とは、基本データ型のように箱の中に値そのものが入っているわけではありません。値をその箱の中に格納して保管するのではなく、箱が置かれている場所を参照する変数のことを言います。
たとえば以下のプログラムのように配列をコピーして、コピーした配列の値を変更するとどうなるのか確認してみましょう。
public class Main { public static void main(String[] args) throws Exception { // 配列を宣言 int array1[] = {10,20,30}; int array2[] = array1; array2[0] = 100; System.out.println(array1[0]); } }
実行結果:
100
このように配列array1をコピーしたarray2の値を変更しても、参照している場所は同じのため、コピー元の配列も値が変更されます。
ShallowコピーとDeepコピー
配列をコピーして、コピー先の配列の値を変更してしまうとコピー元の配列も変更されてしまうので注意が必要です。このように参照のみコピーすることを「Shallowコピー(浅いコピー)」と言います。
配列をコピーして別の配列として使いたい場合は「Deepコピー(深いコピー)」と言って、「配列に値を追加してみよう」で解説したようにarraycopyで別の配列を新たに作る方法が有効です。
Javaについてもっと知りたい方へ
ここでは、Javaの配列についてわかりやすく解説してきました。プログラミングを身につけるためには、たくさんのトライ・アンド・エラーが必要です。しかし、Javaはできることがたくさんある分、非常に奥の深い言語です。
Javaのスキルを身に着けられるか不安・・・
Javaを体系的に勉強したい
と感じている方は以下の記事も合わせてご覧ください。
Javaの概要から基本的な使い方まで網羅していますので、きっと参考になるのではと思います。
まとめ
今回はJavaの配列について、配列の仕組みから基本や応用的な使い方、気をつけたいポイントまで網羅的に解説しました。
配列は覚えてしまえばとても便利なものであることがわかったと思います。しかし配列でできることは非常に多く、実際の業務では配列を駆使してさまざまな処理を行うことになりますので、使い方についてはしっかりとマスターしておきましょう。