Java
2021.12.02
JavaのList型について解説!arrayListの使い方・便利なメソッドまとめ
2023.11.18

1.JavaのListとは

Javaには、複数のオブジェクトを管理するために「配列」という仕組みがあります。しかし配列は事前に要素の数を決める必要があり、様々な処理が必要となる要素の管理には適していません。


その代わり、Javaにはこれらを一つのグループとして表現するためのクラスやインターフェースを定義した「コレクション・フレームワーク」があります。その中の一つに「List」があるのです。


Listは、格納された要素を順番にインデックスを付けて管理することが特徴です。他にも、重複したデータでも格納できる、既存のインデックスを指定して割り込ませるようなデータ追加が可能といった特徴があります。


拡張for文やitaratorなどを使用し、一つ目の要素から順番に処理を行えるため、インデックスを利用できる順番・比較などの処理と相性がよいです。またコレクションクラスを継承しているため、配列では使えない様々なメソッドを利用できることも「List」を使うメリットの一つです。

1-1. ArrayListとは?Listとの違いは?

ArrayListとLIstについて、何が違うか分かりづらいと思います。複数の要素を扱うためにListという設計(インターフェース)があり、その仕様を継承したクラスが「ArrayList」です。つまり、ListはArrayListの上位概念に当たります。


では、どちらを使えばよいのでしょう。まずListはあくまでインターフェースであるため、実際の要素を格納するインスタンスの生成ができません。よってArrayListとして以下のようにインスタンスを生成します。

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

コレクション・フレームワークの中でも、ArrayListは「i番目の要素を取り出す」という処理が早いという特徴を持っています。

1-2. Listと配列の違い

まずListと配列の定義方法を見てみましょう。

//配列
String sample_array[] = { "あ", "い", "う", "え", "お" };

//ArrayList
List<String> sample_arraylist = new ArrayList<>(Arrays.asList("あ", "い", "う", "え", "お"));

上記のコードでは、インスタンス作成時点はどちらも構造上同じように見えます。ただし、配列の場合は要素数をあらかじめ決めなければいけません。


一方で、ArrayListの場合、要素の追加や削除が自由に行えることに加えて、クラスに備わる利便性の高い様々なメソッドが利用できます。


要素に対して変更などの処理が行われる場合はArrayListを使い、都道府県など要素数が確定している場合には配列を使うのがよいでしょう。



2.Listの基本的な使い方


Listについて確認できたところで、ここからは使い方を解説していきます。

2-1. 基本ルール

Listインターフェースは、index(要素番号)を0から順番に格納していくコレクションです。はじめにメモリ上に領域を確保する配列と異なり、Listは新しい要素が追加されるたびにメモリの領域を確保できるため、要素数を宣言する必要はありません。


Listを使用するには、まずJava.utilのパッケージをインポートする必要があります。またインスタンス作成時には、Listに入る要素の型とListインターフェースを継承したクラスを指定する必要があります。

2-2. Listの宣言・初期化方法

実際にListを宣言する際には、以下のように記載します。

List<データ型名> オブジェクト名 = new ArrayList<データ型名>();
//例
List<String> hiragana_list = new ArrayList<String>();

要素を格納していき、toStringメソッドを使って出力する際には以下のように記載します。

hiragana_list.add("あ");
hiragana_list.add("い");
hiragana_list.add("う");
hiragana_list.add("え");
hiragana_list.add("お");
hiragana_list.add("あ");
System.out.println(hiragana_list.toString())
// [あ, い, う, え, お, あ]が出力される


3.ループを使ったListへのアクセス


ここでは、for文などのループ処理を使いListへアクセスする方法を解説します。

3-1. iteratorを使ったfor文でアクセス

コレクションのすべての要素にアクセスすることを考えた場合、MapやSetなどインデックスではアクセスできないものもあります。


Iterator(イテレータ)というインターフェースを使用すると、クラスの違いに依らない反復処理が行えるため、ソースコードがシンプルになります。また、処理が速くなることがあるので、使い方を覚えておくとよいでしょう。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List

public class SampleIterator {
    public static void main(String[] args) {
        // Listの生成
        List<String> list = new ArrayList<>(Arrays.asList("か","き","く"));
        Iterator<String> list_iterated = list.iterator();
        String moji;
        //while文とhasNextメソッドでループ
        while (list_iterated.hasNext()) {
            moji = list_iterated.next();
            System.out.println(moji); //か, き, くと順番に出力される  
        }
    }
}

hasNextメソッドは、処理実行後にまだ要素がある場合にtrueを返します。よって、すべての要素にアクセスが終わるまでwhile以下の処理が行われます。このコードの実行結果から、ArrayListで宣言した要素がすべて出力されることがわかりますね。

3-2. forEachメソッドでアクセス

iteratorを使用する以外にも、コレクションの要素にアクセスする方法はあります。

forEachメソッドは、繰り返しが要素数の分だけ行われます。通常のfor文で行っていた配列.lengthが不要となるのです。

import java.util.ArrayList;
import java.util.List;
 
public class Sampleforeach {
    public static void main(String[] args) throws Exception {
        // Listの生成
        List<String> list = new ArrayList<>(Arrays.asList("か","き","く"));
        // forEachメソッド文でループ
        list.forEach(moji -> System.out.println(moji));
        // か, き, くと順番に出力される  
    }
}

iteratorを使った書き方よりもスッキリ見えますが、Iteratorとは異なり別のコレクションでは書き方が異なるなど制約もあるので注意しましょう。


4.Listのよく使用するメソッド一覧

ここからは、よく使用するListのメソッドを紹介します。

4-1. 要素の追加に関するメソッド

・addメソッド

Listに要素を挿入するには、add()メソッドを以下のように記載します。

List <String> sample_list = new ArrayList <>();
sample_list.add("赤");

・addAllメソッド

一つの要素を挿入するaddに対して、addAllは引数として渡されたコレクションのすべての要素を挿入できます。

List<String> sample_list_1 = new ArrayList<>(Arrays.asList("赤", "青", "緑"));
List<String> sample_list_2 = new ArrayList<>();
sample_list_2.addAll(sample_list_1l);
System.out.println(sample_list_2.toString());
// [赤, 青, 緑]と出力される

・setメソッド

setメソッドを使うことで、すでに格納されている値を別の値に置き換えられます。

List<String> sample_list = new ArrayList<>(Arrays.asList("赤", "青", "緑"));
sample_list.set(2, "白");
// Listの中身は[赤, 青, 白]

4-2.要素の取得・検索に関するメソッド

・getメソッド

Listの要素はgetメソッドで取得できます。

List<String> sample_list = new ArrayList<>(Arrays.asList("赤", "青", "緑"));
System.out.println(sample_list.get(2));
// インデックス(2)の緑が出力される

・sizeメソッド

sizeメソッドは要素の個数を取得できます。

List<String> sample_list = new ArrayList<>(Arrays.asList("赤", "青", "緑"));
System.out.println(sample_list.size() + "が要素数です。");
// 「3が要素数です。」が出力される

・subListメソッド

subListメソッドを使うと、リストから一部分を切り取ることが可能です。

List<String> sample_list1 = new ArrayList<>(Arrays.asList("赤", "青", "緑", "黒", "白"));
List<String> sample_list2 = sample_list1.subList(1,4);
System.out.println(sample_list2);
// [青,緑,黒]が出力される

・indexOfメソッド

indexOfメソッドは、リストから要素を検索する際に利用できます。

以下の例だと、”白”のインデックスである1を返します。

List<String> sample_list = new ArrayList<>(Arrays.asList("黒", "白", "緑", "赤", "青", "緑", "黒", "白"));
int n = sample_list.indexOf("白");
System.out.println( n + "番目にありました");

・lastIndexOfメソッド

先頭から検索するindexOfメソッドに対して、lastIndexOfメソッドは後ろから検索し、最初に見つかった位置のインデックスを返します。以下の場合は7が返ります。

List<String> sample_list = new ArrayList<>(Arrays.asList("黒", "白", "緑", "赤", "青", "緑", "黒", "白"));
int n = sample_list.lastIndexOf("白");
System.out.println( n + "番目にありました");

・containsメソッド

containsメソッドは特定の値がリストに含まれているかを確認できます。

List<String> sample_list = new ArrayList<>(Arrays.asList("赤", "青", "緑", "黒", "白"));
if(sample_list.contains("緑")) {
    System.out.println("リスト内に値が存在しています。");
}

・isEmptyメソッド

isEmptyメソッドはコレクションが空かどうか判定し、trueもしくはfalseを返します。

List<String> sample_list = new ArrayList<>(Arrays.asList( ));
if (sample_list.isEmpty()) {
    System.out.println("リストは空です。");
}

・sortメソッド

sortメソッドを使えば、リストを指定した順番に並び替えることが可能です。

ArrayList<Integer> num_list = new ArrayList<>(4, 25, 20, 61,39);

Collections.sort(num_list);
System.out.println(num_list);
// [4, 20, 25, 39, 61]が出力される

4-3.要素の削除に関するメソッド

・removeメソッド

インデックスを指定してremoveメソッドを使用すると、要素が削除されます。

List<String> sample_list = new ArrayList<>(Arrays.asList("赤", "青", "緑", "黒", "白"));
sample_list.remove(2);
// リストは[赤、青、黒、白]となる

・distinctメソッド

重複した要素がある場合は、distinctメソッドで重複を無くせます。

List<String> sample_list = new ArrayList<>(Arrays.asList("赤", "青", "赤", "黒", "青"));
List<String> distinct_list = sample_list.stream().distinct().collect(Collectors.toList());
System.out.println(distinct_list);
// [赤、青、黒]と重複が無くなり出力される

・clearメソッド

clearメソッドで、リストからすべての要素を削除できます。

List<String> sample_list = new ArrayList<>(Arrays.asList("赤", "青", "緑", "黒", "白"));
sample_list.clear();
System.out.println(sample_list.size());
//0と出力され、リストの要素が空になったことが分かる




5.List・Set・Mapの違いと特徴


これまでListの使い方やクラスが持つメソッドを紹介してきました。ここからは、Listと同じく配列を扱うクラスである「Set」や「Map」との違いについて解説します。


様々なクラスが入っているjava.utilパッケージの中で、配列を操作するための代表的なクラスが「List」「Set」「Map」です。


値を順に並べ格納したListとの違いとして、Set・Mapはまずデータの構造が異なります。

それぞれ特徴を詳しく見ていきましょう。

5-1.Setとは

Setは、要素をインデックスで順番付けせずに管理するデータ構造で、同じ値のものが一つだけという特徴があります。また、HashSetとTreeSetの2種類の継承クラスがあります。


Setには、インデックスのように特定の要素にアクセスするためのキーがありません。そのため、要素の取得にはIteratorや拡張for構文などすべての要素にアクセスする構文を使用しましょう。


特定のデータが何種類あるのか、ある要素はデータに存在するかなどを調べる時に役立ちます。


HashSetは要素の取得順を指定できませんが、TreeSetを使えばソート順をコントロールできます。さらに、HashSetは要素にnullを設定できますが、TreeSetはnullを設定できないという違いがあるので覚えておきましょう。

5-2.Mapとは

Mapは、キーとバリューをセットにしたものを一つの要素として管理するデータ構造です。


インデックスの代わりに任意の変数を要素の値のペアにでき、連想配列の形をしています。キーはユニーク(重複がない)である必要がありますが、バリューは同じものが複数あっても大丈夫です。


Mapの要素を操作する時は、キーを指定してペアであるバリューの取得・更新・削除を行います。検索機能のように、キーが任意に与えられるような場面での使用に適していると言えるでしょう。


HashMapは格納順は管理されませんが、TreeMapは順序がキーの順番になっています。また、HashMapはキーとバリューにnullを使用することが可能ですが、TreeMapではnullは使用できません。



6.Listとその他コレクション・配列の変換方法


これまでListを中心に関連するMapやSet、配列について説明してきました。実際のプログラミングでは、使用したい処理ができるクラスで変数が与えられないこともあります。


ここでは、配列やSet、Map型とListの変換方法を解説します。

6-1.配列とListの変換

・配列からListへの変換

配列からリストへは、asListメソッドを使用して変換します。

String[] sample_array = { "は", "い", "れ", "つ" };
List<String> sample_list = Arrays.asList(sample_array);

・Listから配列への変換

反対にリストから配列への変換する場合は、toArrayメソッドを使用します。

List<String> sample_list = new ArrayList<>(Arrays.asList("リ", "ス", "ト"));
String[] sample_array = sample_list.toArray(new String[sample_list.size()]);

6-2.SetのListの変換

・ListからSetへの変換

ListからSetへの変換は簡単で、Set型のインスタンス宣言時にリスト型の変数を渡します。

List<String> sample_list = new ArrayList<>(Arrays.asList("リ", "ス", "ト"));
Set<String> sample_set = new HashSet<String>(sample_list);

・SetからListへの変換

SetからLIstの変換も同様に、List型のインスタンス宣言時にセット型の変数を渡します。

Set<String> sample_set = new HashSet<String>();
Collections.addAll(sample_set, "セ", "ッ", "ト");
List<String> sample_list = new ArrayList<String>(sample_set);

6-3.MapとListの変換

・ListからMapへの変換

キーとバリューを持つMapにListを変換するのはSetと比べると少し難しいです。

for文などを利用して、キーとバリューを指定し、Mapに格納していきます。

List<String> sample_list = new ArrayList<>(Arrays.asList("リ", "ス", "ト"));
Map<Integer, String> sample_map = new HashMap<>();
for(int i = 0; i < sample_list.size(); i++) {
    String value = sample_list.get(i).toString();       
    sample_map.put(i, value);
}
// sample_map = (0=リ, 1=ス, 2=ト)

・MapからListへの変換

反対にMapからListへの変換は、valuesメソッドでバリューを指定して、List宣言時に渡します。キーをListにしたい場合はkeySetメソッドも利用できます。

Map<String, String> sample_map = new HashMap<>();
sample_map.put(“first", "マ");
sample_map.put(“second", "ッ");
sample_map.put(“third", "プ");
List<String> sample_list = new ArrayList<>(sample_map.values());
// sample_list = [マ, ッ, プ]




この記事をシェア