自分でサイズを変えるリスト
Javaの通常の配列は固定長です。10個の枠に決めたら、ずっと10個の枠のままです。ArrayList は java.util にあるサイズ可変の代替手段で、追加すれば伸び、削除すれば縮み、リストで実際に行う操作のための便利なメソッドを備えています。
山かっこ内の型 - List<String> - に注目してください。これはこのリストが String の値を保持することをコンパイラに伝えます。右側の <>(「ダイヤモンド」)により、Javaは同じ型を繰り返さずに推論できます。また java.util.ArrayList をインポートしている点にも注意してください。デフォルトでは利用できません。
Listとして宣言し、ArrayListとして生成する
変数は、具体的な ArrayList ではなく List インターフェースの型で宣言されているのをほぼ常に目にするでしょう:
List<String> names = new ArrayList<>();
これは規則ではなく良い習慣です。List インターフェースに対してコーディングするということは、コードの残りの部分がどのリスト実装を使ったかを気にしないということなので、後でそれに手を加えずに別の実装へ差し替えられます。日常的な利用では、両者の振る舞いは同じです。
追加、取得、変更
add(value)は末尾に追加します。add(index, value)はある位置に挿入し、後ろの要素を右へずらします。get(index)はある位置の要素を読み取ります(0始まり)。set(index, value)は既存の要素を上書きします。
インデックスは0始まりで、範囲外のインデックスに対する get は IndexOutOfBoundsException をスローします。
要素の削除
リストが Integer を保持しているときには、古典的な落とし穴があります。remove(int) は「インデックスで削除」、remove(Object) は「値で削除」を意味するので:
List<Integer> nums = new ArrayList<>(List.of(10, 20, 30));
nums.remove(1); // インデックス1を削除 -> 値の20
nums.remove(Integer.valueOf(20)); // 値の20を削除
「このインデックスを削除」ではなく「この値を削除」したいときは、値を Integer.valueOf(...) で包んでください。
サイズ、contains、インデックス検索
List.of(...) は手軽にイミュータブルなリストを作ります。それを ArrayList のコンストラクタに渡すと、それらの値で初期化されたミュータブルなコピーが得られます。
ArrayListをループする
最もすっきりしたループは拡張 for(「for-each」)です:
インデックスも必要なときは、size() と get(i) を使うカウンタ付きループを使います:
1つの鉄則:for-eachループがリストを反復している最中に、そのリストへ要素を追加したり削除したりしてはいけません - ConcurrentModificationException をスローします。一致する項目を安全に削除するには removeIf を使います:
ソート
Collections.sort は自然順序(文字列なら辞書順、数値なら数値順)を使って、リストをその場で並べ替えます:
独自の並び順には、list.sort(...) に Comparator を渡します - たとえば長さでソートするなら names.sort(Comparator.comparingInt(String::length)) です。
ArrayListはプリミティブではなくオブジェクトを保持する
ArrayList<int> とは書けません。ジェネリクスはオブジェクト型でしか機能しないため、ラッパークラスの Integer、Double、Boolean などを使います:
Javaのオートボクシングが int と Integer の間の変換を肩代わりするので、自然に読めます - ただしリスト自体は Integer オブジェクトを格納していることだけは忘れないでください。
次は:HashMap
ArrayList は、順序や位置が重要なときに適したツールです。キーで値を引きたいとき - ユーザー名からユーザーへ、商品コードから価格へ - には HashMap が必要で、それが次のページです。
よくある質問
JavaでArrayListはどうやって作成しますか?
要素の型を山かっこで指定して宣言し、コンストラクタを呼び出します:ArrayList<String> names = new ArrayList<>();。右側の <>(ダイヤモンド演算子)により、Javaが型を推論します。通常は変数を List インターフェースの型で宣言します:List<String> names = new ArrayList<>();。
Javaにおける配列とArrayListの違いは何ですか?
通常の配列は作成時に長さが決まる固定長で、int のようなプリミティブを保持できます。ArrayList は要素を追加・削除するにつれて自動的に伸び縮みし、オブジェクトのみを保持し(そのため int は Integer になります)、add、remove、contains、size などのメソッドを備えています。固定サイズのプリミティブなデータには配列を、サイズが変わる場合には ArrayList を使いましょう。
ArrayListから要素を削除するにはどうすればいいですか?
位置で削除するには remove(index) を、最初に一致した要素を削除するには remove(object) を呼び出します。Integer のリストでは注意が必要です:list.remove(2) はインデックス2を削除し、list.remove(Integer.valueOf(2)) は値の2を削除します。ループ中に削除する場合は、ConcurrentModificationException を避けるために Iterator の remove() か removeIf(...) を使ってください。