【本サイトではGoogleアドセンス、または、アフィリエイト広告を利用しています。】
Listとは?配列との違いは?コレクションとは?
Listとは、Javaに標準で用意されているインターフェースの1つです。
複数のデータをリスト化することで様々な操作を行うことができます。
Listは、「java.util」という名前のパッケージに定義されていて、
インポートすることで使えるようになります。
複数のデータを扱う点で配列とよく似ていますが、
単純なデータの集まりとして定義される配列に対して、
Listはリスト全体を1つのインターフェース(クラス)として定義したものなので、
リストを操作する為の便利なメソッドを呼び出して扱うことができます。
また、Listでは、宣言時に要素数の指定をする必要がありません。
必要な時に追加したり、削除してデータの中身を書き換えることができます。
Listのような複数のデータを操作する為に定義されたクラスを
コレクションと呼ぶのであわせて覚えておきましょう!
配列についてはこちらで解説していますので、
あわせて読んでいただくとより理解が深まると思います。
ArrayListとは?
ArrayListとは、Javaに標準で用意されているリストを扱うクラスの1つです。
Listインターフェースを実装しており、
複数のデータを操作する為のリストを扱う際は
基本的にArrayListをインスタンス化して使います。
(Listはインターフェースなので、単体ではインスタンス化して使えません。)
ArrayListには、要素の追加、削除、コピーなど
リストを扱う際に便利な様々なメソッドが用意されています!
では、今からサンプルコードとあわせて使い方を説明していきます!
リストの宣言
リストは以下の形で宣言します。
Listインターフェースの変数に、ArrayListを代入する①の方法と、
通常通り、ArrayListの変数に、ArrayListを代入する②の方法があります。
List<データの型> リストの名前 = new ArrayList<データの型>();
ArrayList<データの型> リストの名前 = new ArrayList<データの型>();
また、List、ArrayListを使う為には、
使用するクラスの先頭に以下のインポート宣言が必要です。
import java.util.ArrayList;
import java.util.List;
用途によって2つの宣言方法を変えていくのですが、基本的には①で大丈夫です。
インターフェース型のListでArrayListを受ける理由としては、
リストの型はArrayListだけではなく、他にもListインターフェースを実装している
様々なクラスが用意されており、状況に従って、
Listを他のクラスに変換しやすくする為です。
Listはインターフェースなので、Listを実装しているクラスであれば、
どんな型でも代入できます。ArrayListを最初に入れていたとして、
例えば、ArrayListで扱っていたデータをLinkedListと呼ばれる
別のコレクションクラスに変換したものをそのままListの変数に入れて扱うことができます。
ただし、ArrayListが持つ固有のメソッドは①の宣言では使えないので、
(Listインターフェースが持つメソッドしか使えない。)
ArrayListが持つ固有のメソッドを使いたい場合は、
②の方法で宣言するといった使い方をする必要があります。
ジェネリクスとは?
宣言する際に使う「<>」で囲うデータ型のことをジェネリクスと呼びます。
コレクションクラスを扱う場合は、リストで扱うクラスの型が
数値なのか文字列なのか、Javaに伝えておく必要があります。
例えば、文字列のリストを並べ替える場合と、
数値のリストを並べ替える場合では、比較する方法が違ってきます。
単純にデータをリストに入れて、並べ替えてくれとJavaに命令しても、
どのようにデータを比較すればよいのか判断がつかないので、
ジェネリクスを使って型を指定してあげる必要があるのです。
間違った型を指定すると、リストを操作する際にエラーとなったり、
意図しない動作をしてしまうので気をつけましょう。
リストに要素を追加する(add)
リストに要素を追加する、つまりデータを1つ追加する方法です。
「add」メソッドを使って、引数に追加するデータを指定します。
List<String> strList = new ArrayList<String>();
strList.add("リンゴ");
strList.add("ゴリラ");
strList.add("ラッパ");
これでstrListリストに「リンゴ」「ゴリラ」「ラッパ」という
文字列が順番に追加されます。
例では引数に文字列を直接指定していますが、String型の変数を指定することもできます。
String apple = "リンゴ";
strList.add(apple);
データを追加する時は、ジェネリクスで指定した型に気をつけましょう。
リストの要素を取り出す・参照する・アクセスする(get)
リスト内にある要素は、「get」メソッドで取得することができます。
引数に要素番号を指定して使います。
先頭の要素を出力してみましょう。
List<String> strList = new ArrayList<String>();
strList.add("リンゴ");
strList.add("ゴリラ");
strList.add("ラッパ");
System.out.println(strList.get(0));
実行結果は以下です。
リンゴ
例では、出力処理の中で直接指定しましたが、
String型の変数に代入してから出力することもできます。
String firstStr = strList.get(0);
System.out.println(firstStr);
また、配列と同様に、要素数「0」がリストの先頭になることに注意してください。
リストの要素を削除する(remove)
リスト内にある要素は、「remove」メソッドで削除できます。
List<String> strList = new ArrayList<String>();
strList.add("リンゴ");
strList.add("ゴリラ");
strList.add("ラッパ");
strList.remove(0);
リスト内の要素数を指定することで、特定の要素を削除できます。
例の場合は先頭要素を削除するので「0」を指定しています。
また、こうすることで、先頭要素は「ゴリラ」になります。
要素が1つ消えると、その後ろの要素番号も順番に1つずつずれていくので
要素を指定する処理を扱う時は削除処理との関連に注意しましょう。
リストの要素数を調べる(size)
リストの要素数、つまり、リストに入っているデータの数は
「size」メソッドで取得できます。
List<String> strList = new ArrayList<String>();
strList.add("リンゴ");
strList.add("ゴリラ");
strList.add("ラッパ");
System.out.println(strList.size());
実行結果は以下です。
3
値はint型で返ってくるので、int型の変数に代入して使うこともできます。
リストを使ってループする
ループ構文を使って、リストの中に入っているデータを
順番に操作する方法は以下です。
まずは、for文を使ってみます。ループで使っている
カウント用の変数「i」の初期値を「0」としてgetメソッドの引数に使えば、
ループする毎にリストに入っているデータを順番に取得できます。
List<String> strList = new ArrayList<String>();
strList.add("リンゴ");
strList.add("ゴリラ");
strList.add("ラッパ");
for (int i = 0; i < strList.size(); i++) {
System.out.println(strList.get(i));
}
実行結果は以下です。
リンゴ
ゴリラ
ラッパ
また、Listに用意されているforEachメソッドを使うと、
この処理は以下のように1行で書くことができます。
strList.forEach(str -> System.out.println(str));
forEachメソッドの中はラムダ式と呼ばれる構文を使います。
書き方としては以下のようになります。
リスト名.forEach(繰り返し処理で使う要素の名前 -> 繰り返し処理);
繰り返し処理は、「{}」で囲うことで複数処理を記載できます。
また、繰り返し処理の中で使うリストの要素を「->」の前に指定します。
例えば、複数処理を書く場合はこんな感じです。
strList.forEach((str) -> {
System.out.println("要素を取り出します。");
System.out.println(str);
});
実行結果は以下です。
要素を取り出します。
リンゴ
要素を取り出します。
ゴリラ
要素を取り出します。
ラッパ
forEachを使うことで、for文より見た目としては
シンプルなプログラムにはなりますが、
Javaに慣れていない人にとっては読みにくいという面もありますし、
処理の対象となっている現在の要素数を取得するのに一工夫必要になる為、
メンテナンス性が良いかというとそうでもありません。
無理にforEach(ラムダ式)を使う必要はありません。
基本的にはfor文を使ってループ処理をしましょう!
リストを初期化する
Listを初期化する方法を考えた時、基本的にはListを宣言した後に、
forでループしてaddでデータを追加していく方法がありますが、
他にも方法があるのでご紹介します。
書き方は以下です。
Arraysクラスの「asList」メソッドを引数の中で呼び出すことで
ArrayListの要素を指定できます。
List<データの型> リストの名前 = new ArrayList<データの型>(Arrays.asList(要素0, 要素1, ・・・));
また、Arraysクラスを使う為には、
使用するクラスの先頭に以下のインポート宣言が必要です。
import java.util.Arrays;
先ほどの例と同じように、文字列を3つリストに追加した状態で
ArrayListを定義するとこんな感じです。
List<String> strList = new ArrayList<String>(Arrays.asList("リンゴ", "ゴリラ", "ラッパ"));
あらかじめ追加するデータが決まっている場合は、
Listの宣言と同時にデータ追加できるので便利です。
リストをソートする(昇順・降順で並び替え)
Listに入っているデータを昇順・降順に並べ替えたい時は
Collectionsクラスの「sort」メソッドを使います。
sortメソッドの第1引数には、ソート対象のリスト、
第2引数には、並び替え方法を指定します。
昇順ソートの使い方は以下です。
昇順ソートを行いたい時は、第2引数を省略できます。
List<String> strList = new ArrayList<String>(Arrays.asList("リンゴ", "ゴリラ", "ラッパ"));
Collections.sort(strList);
strList.forEach(str -> System.out.println(str));
また、Collectionsクラスを使う為には、
使用するクラスの先頭に以下のインポート宣言が必要です。
import java.util.Collections;
実行結果は以下です。
ゴリラ
ラッパ
リンゴ
降順ソートを行う場合は以下です。降順ソートをする時は、第2引数に
Collectionsクラスの「reverseOrder」メソッドを指定します。
List<String> strList = new ArrayList<String>(Arrays.asList("リンゴ", "ゴリラ", "ラッパ"));
Collections.sort(strList, Collections.reverseOrder());
strList.forEach(str -> System.out.println(str));
実行結果は以下です。
リンゴ
ラッパ
ゴリラ
リストをソートする(自作のルールで並び替え)
単純に昇順、降順だけではなく、自作のルールに従って
リストにあるデータを並び替えする方法について説明します。
ここでは、Collections.sortメソッドの第2引数に
並び替える方法を指定する部分がポイントになります。
先ほど降順ソートでは、Collections.sortメソッドの第2引数に
Collectionsクラスで定義されている方法を指定しましたが、
この第2引数に渡す方法を自作すれば良いわけです。
自作の方法としては、Comparatorクラスの持つcompareメソッドを
オーバーライドして中の処理を自分流に書き換えます。
サンプルコードを見ていきましょう。
今回は、ロボット君を3体作成して、
エネルギーの小さい順で並び替えたいと思います。
まずは並び替えで使うロボット君クラスです。
package example;
// クラス:ロボット
public class Robot {
// フィールド:名前
public String name;
// フィールド:エネルギー
public int energy;
// コンストラクタ
public Robot(String name, int energy) {
this.name = name;
this.energy = energy;
}
// メソッド:自己紹介
public void selfIntroduction() {
System.out.println(name + "デス!エネルギーハ「" + energy + "」デス!");
}
}
メインクラスです。
1~3号のロボットを作成してソートします。
package example;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
// クラス:メイン処理実行用
public class Example {
// メイン処理
public static void main(String[] args) {
Robot robo1 = new Robot("ロボット君1号", 300);
Robot robo2 = new Robot("ロボット君2号", 200);
Robot robo3 = new Robot("ロボット君3号", 100);
List<Robot> roboList = new ArrayList<Robot>(Arrays.asList(robo1, robo2, robo3));
Collections.sort(roboList, new Comparator<Robot>() {
@Override
public int compare(Robot a, Robot b) {
if (a.energy > b.energy)
return 1;
else if (a.energy < b.energy)
return -1;
else
return 0;
}
});
roboList.forEach(robo -> robo.selfIntroduction());
}
}
Comparatorクラスのcompareメソッドをオーバーライドして
中身の処理を書き換えています。
ソートのルールとして、第1引数の要素(例ではRobot「a」)を
リストの後方に1つ移動する時は「1」、前方に1つ移動する時は「-1」、
そのままの場合は「0」を返すようにします。
実行結果は以下です。
ロボット君3号デス!エネルギーハ「100」デス!
ロボット君2号デス!エネルギーハ「200」デス!
ロボット君1号デス!エネルギーハ「300」デス!
エネルギー順にうまく並び替えできました!
特定の要素を検索する(indexOf)
探したい要素が入っている場所を調べるには、
Listの「indexOf」メソッドを使います。
List<String> strList = new ArrayList<String>(Arrays.asList("リンゴ","ゴリラ","ラッパ"));
System.out.println(strList.indexOf("ゴリラ"));
実行結果は以下です。
1
要素が存在しない場合は「-1」の数値が返ってきます。
要素が入っているかどうかを調べる(contains)
リストに指定の要素が入っているかどうか調べるには、
Listの「contains」メソッドを使います。
List<String> strList = new ArrayList<String>(Arrays.asList("リンゴ","ゴリラ","ラッパ"));
System.out.println(strList.contains("ゴリラ"));
実行結果は以下です。
true
戻り値はboolean型です。リストに指定の要素がある場合は「true」
ない場合は「false」が返ってきます。
リストをコピーする(clone)
リストをコピーするには、ArrayListクラスの「clone」メソッドを使います。
Listに「clone」メソッドはないので、
ArrayListとして変数を宣言する必要があることに注意しましょう。
ArrayList<String> strList = new ArrayList<String>(Arrays.asList("リンゴ", "ゴリラ", "ラッパ"));
// リストをコピー
ArrayList<String> strListCopy = (ArrayList<String>) strList.clone();
// コピーしたリストを昇順ソート
Collections.sort(strListCopy);
System.out.println("【strListの中身】");
strList.forEach(str -> System.out.println(str));
System.out.println("【strListCopyの中身】");
strListCopy.forEach(str -> System.out.println(str));
コピーしたリストは、Object型としてcloneメソッドから返ってくるので、
コピー元の型にあわせて「()」でキャストして代入する必要があります。
コピーしたリストを昇順で並び替えてから、
コピー元、コピーリストそれぞれの中身を出力してみました。
【strListの中身】
リンゴ
ゴリラ
ラッパ
【strListCopyの中身】
ゴリラ
ラッパ
リンゴ
コピー元のリストの中身に影響させることなく、
コピーリストを並び替えることができている部分もポイントの1つです。
リストの中を空にする(clear)
Listの中を空にするには、Listの「clear」メソッドを使います。
List<String> strList = new ArrayList<String>(Arrays.asList("リンゴ", "ゴリラ", "ラッパ"));
System.out.println("クリア前の要素数は「" + strList.size() + "」です。");
strList.clear();
System.out.println("クリア後の要素数は「" + strList.size() + "」です。");
実行結果は以下です。
クリア前の要素数は「3」です。
クリア後の要素数は「0」です。
リストの使い方 まとめ
JavaのListについて以下説明しました。
・Listについて
・コレクションについて
・ArrayListについて
・ジェネリクスについて
・リストの宣言方法
・要素の追加(add)、参照(get)、削除(remove)
・要素数を調べる方法(size)
・リスト使ったループ(for、forEach)
・リストの初期化
・リストのソート(降順・昇順、自作の条件)
・要素の検索(indexOf、contains)
・リストのコピー(clone)
・リストのクリア(clear)
ListはJavaプログラミングをする上で最も重要になってくる構文です。
知らずに頑張って書いた処理が、
Listのメソッドたった1行で実現できた、なんてこともあります。
使い方次第で、シンプルかつ効率の良いプログラミングをすることができるので
ぜひマスターしておきましょう!