Java | Java 標準ライブラリ:List / ArrayList

Java Java
スポンサーリンク

List と ArrayList をざっくりイメージする

まずイメージからいきます。

配列 int[] は「長さが固定の箱の列」でした。
一方で List / ArrayList は「あとから増やしたり減らしたりできる箱の列」です。

List は「こういう振る舞いをする“列”の抽象的な型(インターフェース)」、
ArrayList は「List の具体的な実装クラス(中身は配列ベース)」だと思ってください。

コードで書くと、よく見るのはこういう形です。

List<String> list = new ArrayList<>();
Java

左側の List は「どんな振る舞いをするか」の約束。
右側の new ArrayList<>() が「実際の中身(配列を使っているクラス)」です。

「基本的には List で変数を宣言しておき、中身として ArrayList を new する」
この形が Java では“お作法”に近いです。


配列と List / ArrayList の違いを最初にハッキリさせる

長さが固定か、増減できるか

配列は一度作ったら長さを変えられません。

int[] a = new int[3];   // 長さ 3 で固定
// あとから「長さ 4 にしたい」はできない
Java

ArrayList は、要素を add するたびに内部でうまく拡張してくれます。

List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30);
// いくらでも add していける(メモリが許す限り)
Java

「あとから数が増える可能性があるデータ」は、基本的に List / ArrayList で持つと思ってください。

型の書き方(プリミティブは直接入らない)

配列なら、int[]double[] のようにプリミティブ型を直接使えます。

int[] a = new int[3];
Java

しかし List は「オブジェクトのコレクション」なので、プリミティブはそのまま入れられません。
代わりにラッパークラス(Integer, Double など)を使います。

List<Integer> list = new ArrayList<>();
list.add(10);   // オートボクシングされて Integer になる
Java

List<int> とは書けない、ここを一度ちゃんと意識しておくと混乱が減ります。


ArrayList の基本操作(add / get / size / remove)

要素を追加する add

ArrayList に要素を入れるのは add です。

List<String> names = new ArrayList<>();

names.add("Alice");
names.add("Bob");
names.add("Carol");

System.out.println(names);  // [Alice, Bob, Carol]
Java

このとき、サイズ(要素数)は 3 です。
あとからいくらでも add できます。配列のように「最初に長さを決める」必要はありません。

要素数を調べる size

要素が何個入っているかは size() で分かります。

System.out.println(names.size());  // 3
Java

配列の length とよく似ていますが、
配列はフィールド(arr.length)、List はメソッド(list.size())です。

要素を取り出す get(インデックスは 0 から)

n 番目の要素を取り出すのは get(index) です。
インデックスは配列と同じく 0 から始まります。

String first = names.get(0);   // "Alice"
String second = names.get(1);  // "Bob"
Java

存在しないインデックス(たとえば 3 以上)を指定すると IndexOutOfBoundsException になります。
ここは配列と同じ感覚です。

要素を削除する remove

remove は大きく二通りあります。

インデックスで削除:

names.remove(1);  // index 1 の "Bob" を削除
System.out.println(names);     // [Alice, Carol]
Java

値で削除:

names.remove("Alice");         // "Alice" に等しい要素を削除
System.out.println(names);     // [Carol]
Java

remove(1) は「インデックス 1 を削除」
remove("1") は「文字列 “1” を削除」

というように、引数の型によって意味が変わるので、ここはよく注意してください。


List を for 文や拡張 for で回す

古典的な for 文で回す

配列と同じように、インデックスで回すパターンです。

for (int i = 0; i < names.size(); i++) {
    String name = names.get(i);
    System.out.println(i + ": " + name);
}
Java

size() は毎回呼んでも問題ないですが、性能を気にするなら事前に変数に入れることもあります。

int n = names.size();
for (int i = 0; i < n; i++) {
    ...
}
Java

拡張 for 文(for-each)でシンプルに回す

インデックスが特に要らないなら、「拡張 for(for-each)」のほうが読みやすくなります。

for (String name : names) {
    System.out.println(name);
}
Java

for (要素の型 変数名 : コレクション) という形です。
中身を順番に全部見るだけなら、この書き方を積極的に使うとコードがきれいになります。


List と ArrayList の関係(インターフェースと実装)

なぜ変数は List 型で持つのか

よくこう書きます。

List<String> names = new ArrayList<>();
Java

「最初から ArrayList で宣言してもよくない?」と思うかもしれません。

ArrayList<String> names = new ArrayList<>();
Java

これでも動きます。ただし、設計としては最初の書き方が好まれます。

理由は、「あとから中身の実装を差し替えやすいから」です。

List というのは、「順番があって、重複を許すコレクション」というインターフェース(振る舞いの約束)です。
ArrayList は、その List を配列ベースで実装したクラスです。

将来、「この List は LinkedList にしたほうが都合が良くなった」となったとき、
変数の型を List にしておけば、右側だけ変えれば差し替えられます。

List<String> names = new LinkedList<>();
Java

「左側は List、右側は具体クラス」という形を癖づけておくと、
設計として柔軟になります(そして現場の Java コードのほとんどがそう書いています)。


よくあるハマりポイントと注意点

new し忘れて NullPointerException

これ、初心者がほぼ全員一度はやらかします。

List<String> names;       // 宣言だけ
names.add("Alice");       // NullPointerException
Java

変数を宣言しただけだと、中身は null のままです。
必ず new ArrayList<>() してから使います。

List<String> names = new ArrayList<>();
names.add("Alice");  // OK
Java

フィールドでも同じです。コンストラクタなどで必ず初期化しましょう。

型パラメータ(<String>)を書き忘れる

List はジェネリクスを使うので、<> の中の型を省略すると「生の型(raw type)」になり、
コンパイラから警告されたり、キャストが必要になったりします。

List list = new ArrayList();  // 推奨されない書き方
list.add("abc");
String s = (String) list.get(0); // キャストが必要
Java

正しくはこうです。

List<String> list = new ArrayList<>();
list.add("abc");
String s = list.get(0); // キャスト不要、型安全
Java

ジェネリクスをちゃんと書くと、コンパイル時に型チェックしてくれるので、
バグが減ります。ここは少し面倒でも、きちんと書いたほうが長期的に得です。


まとめ:List / ArrayList を頭の中でこう整理しておく

最後に、初心者向けに List / ArrayList のイメージをまとめます。

配列は「長さ固定」。List / ArrayList は「あとから増やしたり減らしたりできる列」。
List は「インターフェース(こう振る舞うべきという約束)」、ArrayList は「配列ベースの具体実装」。
宣言は List<型> 変数 = new ArrayList<>(); という形が基本。
要素追加は add、参照は get、要素数は size、削除は remove
for 文・拡張 for 文で自然に回して使う。

タイトルとURLをコピーしました