Javaで学ぶArrayListの12の使い方と応用テクニック – JPSM

Javaで学ぶArrayListの12の使い方と応用テクニック

JavaでArrayListを使いこなす12の方法Java

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

このサービスは複数のSSPによる協力の下、運営されています。

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

また、理解しにくい説明や難しい問題に躓いても、JPSMがプログラミングの解説に特化してオリジナルにチューニングした画面右下のAIアシスタントに質問していだければ、特殊な問題でも指示に従い解決できるように作ってあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Javaでプログラミングをする上で、データの管理は避けて通れない道。特に、配列やリストの扱いは日常茶飯事ですよね。

しかし、初心者からすれば、どのようにうまくデータを管理するかは一筋縄ではいかない問題。

そんなあなたにピッタリなのが、Javaの「ArrayList」です。

この記事ではArrayListの作成から、データの追加、削除、更新、さらには応用テクニックまで、12の具体的な方法をサンプルコードと共に解説します。

この記事を最後まで読むと、ただの初心者からArrayListの使い手に変身できるでしょう。

●ArrayListとは

○定義と基本的な特性

ArrayListとは、Javaで提供されている動的配列の一種です。

動的配列とは、要素数が可変で、実行時にサイズを変更することができる配列のことを指します。

ArrayListはJava標準ライブラリのjava.utilパッケージに属しており、import文を使って簡単にプロジェクトに取り込むことができます。

基本的にArrayListは、内部で通常の配列を用いてデータを管理しています。

しかし、ArrayListが優れている点は、自動でサイズ調整を行ってくれる点です。

つまり、配列のように事前にサイズを指定する必要がないのです。

○なぜArrayListを使うのか

初心者から上級者まで多くのJavaプログラマがArrayListを使う理由はいくつかあります。

第一に、前述の通りArrayListはサイズが動的に変更できるため、データの追加や削除が非常に容易です。

また、ArrayListは様々な便利なメソッドが豊富に用意されています。

例えば、特定の位置にデータを挿入したり、複数のArrayListを結合したりといった高度な操作も簡単に行えます。

さらに、ArrayListはGenerics(ジェネリクス)に対応しているため、任意の型(クラス)のオブジェクトを格納することができます。

これにより、型安全なコードを書くことが可能となり、バグの発生リスクを減らすことができます。

●ArrayListの作り方

○インスタンスの作成

ArrayListの使用を開始するための第一歩は、ArrayListのインスタンス(実体)を生成することです。

Javaでは「new」キーワードを使ってこれを行います。

基本的な構文は次のようになります。

import java.util.ArrayList;  // ArrayListを使うために必要なimport文

public class Main {
    public static void main(String[] args) {
        ArrayList<String> myArrayList = new ArrayList<>();  // String型のArrayListを生成
    }
}

このコードはJavaのArrayListクラスから新しいオブジェクトを生成し、そのオブジェクトをmyArrayListという名前で参照しています。

また、このArrayListはString型の要素を保持することが指定されています。

○イニシャライザを使った初期化

ArrayListは生成と同時に初期データを設定することも可能です。

これをイニシャライザと呼びます。イニシャライザを使用すると、次のようなコードでArrayListを作成できます。

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> myArrayList = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry"));
    }
}

この例では、”Apple”、”Banana”、”Cherry”という三つのString要素でArrayListを初期化しています。

Arrays.asList()メソッドを用いて、固定長のリストを作成し、それをArrayListのコンストラクタに渡しています。

□サンプルコード1:基本的なArrayListの作成

さて、ここでは具体的なコードを通じて、ArrayListの作成方法を総合的に見てみましょう。

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        // 空のArrayListを作成
        ArrayList<Integer> numbers = new ArrayList<>();

        // 初期値を持つArrayListを作成
        ArrayList<String> fruits = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry"));

        // 出力して確認
        System.out.println("numbers: " + numbers);
        System.out.println("fruits: " + fruits);
    }
}

このコードを実行すると、次の出力が得られます。

numbers: []
fruits: [Apple, Banana, Cherry]

このように、numbersは空のArrayListとして生成され、fruitsは”Apple”、”Banana”、”Cherry”で初期化されたArrayListとなります。

●ArrayListに要素を追加する方法

ArrayListが生成された後、次は要素をどのように追加するかというテーマ性があります。

具体的な操作に移る前に、主に使用されるメソッドには二つがあります。

○addメソッド

addメソッドは、ArrayListに新しい要素を追加する基本的な方法です。

このメソッドを用いることで、ArrayListの最後に要素を追加できます。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> animals = new ArrayList<>();  // 空のArrayListを作成
        animals.add("Dog");  // "Dog"を追加
        animals.add("Cat");  // "Cat"を追加
        System.out.println(animals);  // ArrayListの中身を表示
    }
}

このコードでは、まずanimalsという名前で空のArrayListを生成しています。

その後、addメソッドを使って”Dog”と”Cat”という要素を追加しています。

コード実行後、コンソールには[Dog, Cat]と表示されます。

○addAllメソッド

addAllメソッドは、複数の要素をまとめてArrayListに追加するために使用されます。

このメソッドを使えば、別のCollectionオブジェクト(例えば、ListやSetなど)のすべての要素をArrayListに追加することができます。

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> animals = new ArrayList<>(Arrays.asList("Dog", "Cat"));  // 初期要素を持つArrayListを作成
        ArrayList<String> newAnimals = new ArrayList<>(Arrays.asList("Elephant", "Lion"));  // 追加する要素のリスト
        animals.addAll(newAnimals);  // newAnimalsの全要素をanimalsに追加
        System.out.println(animals);  // ArrayListの中身を表示
    }
}

このコードを実行すると、コンソールには[Dog, Cat, Elephant, Lion]と表示される結果が得られます。

それはnewAnimalsの全ての要素がanimalsに追加されているからです。

□サンプルコード2:要素の追加

実際のプログラムでは、単一の要素を追加する場合もあれば、複数の要素を一度に追加する場合もあります。

こちらはその両方のケースを網羅した例です。

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        // 単一の要素を追加
        ArrayList<String> singleAddExample = new ArrayList<>();
        singleAddExample.add("Apple");
        System.out.println("単一要素追加後: " + singleAddExample);

        // 複数の要素を追加
        ArrayList<String> multipleAddExample = new ArrayList<>(Arrays.asList("Apple"));
        ArrayList<String> newFruits = new ArrayList<>(Arrays.asList("Banana", "Cherry"));
        multipleAddExample.addAll(newFruits);
        System.out.println("複数要素追加後: " + multipleAddExample);
    }
}

このサンプルコードを実行すると、最初に単一要素追加後: [Apple]、次に複数要素追加後: [Apple, Banana, Cherry]と表示されます。

これにより、addメソッドは単一の要素を、addAllメソッドは複数の要素をArrayListに追加できることが確認できます。

●ArrayListから要素を削除する方法

ArrayListに要素を追加した後、次なるステップは要素の削除です。

いくらでも要素を追加できるものの、そのままではデータの管理が難しくなる場合もあります。

ここでは、ArrayListから要素を削除する際に使用される主要なメソッドを2つ紹介します。

○removeメソッド

removeメソッドは、特定の要素またはインデックスに基づいて要素を削除します。

このメソッドを使用すると、指定した要素がArrayListから取り除かれます。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> animals = new ArrayList<>();
        animals.add("Dog");
        animals.add("Cat");
        animals.add("Elephant");
        animals.remove("Cat");  // "Cat"という要素を削除
        System.out.println(animals);  // 結果を出力
    }
}

このコードでは、「Dog」、「Cat」、「Elephant」という3つの要素を含むArrayListを生成しています。

そして、removeメソッドを用いて「Cat」という要素を削除しています。

このコードの実行によって出力される結果は[Dog, Elephant]です。

○removeAllメソッド

removeAllメソッドは、複数の要素を一度に削除するためのメソッドです。

引数として別のコレクションを指定すると、そのコレクションに含まれる要素がすべて削除されます。

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> animals = new ArrayList<>(Arrays.asList("Dog", "Cat", "Elephant", "Lion"));
        ArrayList<String> removeList = new ArrayList<>(Arrays.asList("Dog", "Lion"));
        animals.removeAll(removeList);  // removeListに含まれる要素をすべて削除
        System.out.println(animals);  // 結果を出力
    }
}

このサンプルコードでは、「Dog」、「Cat」、「Elephant」、「Lion」という4つの要素が含まれるArrayListから、「Dog」と「Lion」を一度に削除しています。

このコードを実行すると、出力される結果は[Cat, Elephant]です。

□サンプルコード3:要素の削除

要素の削除においても単一と複数、両方のケースが考えられます。

下記のサンプルコードは、その両方のケースをカバーしています。

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        // 単一の要素を削除
        ArrayList<String> singleRemoveExample = new ArrayList<>(Arrays.asList("Apple", "Banana"));
        singleRemoveExample.remove("Apple");  // "Apple"を削除
        System.out.println("単一要素削除後: " + singleRemoveExample);

        // 複数の要素を削除
        ArrayList<String> multipleRemoveExample = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry"));
        ArrayList<String> removeFruits = new ArrayList<>(Arrays.asList("Apple", "Banana"));
        multipleRemoveExample.removeAll(removeFruits);  // "Apple"と"Banana"を削除
        System.out.println("複数要素削除後: " + multipleRemoveExample);
    }
}

このサンプルコードを実行すると、「単一要素削除後: [Banana]」と「複数要素削除後: [Cherry]」が出力されます。

これにより、removeメソッドが単一の要素を、removeAllメソッドが複数の要素を効率よく削除できることが確認できます。

●ArrayListの要素を読み取る方法

要素の追加や削除ができるようになったら、次に必要なスキルはArrayList内の要素の読み取りです。

要素を読み取るためにはいくつかの方法がありますが、ここでは主にgetメソッドとiteratorを用いた走査について詳しく説明します。

○getメソッド

JavaのArrayListではgetメソッドを用いて特定のインデックスに位置する要素を読み取ることができます。

getメソッドは指定したインデックスの要素を戻り値として返します。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        String firstFruit = fruits.get(0);  // インデックス0の要素を取得
        System.out.println("取得した要素: " + firstFruit);
    }
}

上記のコードでは、fruitsという名前のArrayListに「Apple」と「Banana」を追加しています。

その後、getメソッドを使用してインデックス0(最初)の要素を読み取っています。

このコードを実行すると、コンソールに「取得した要素: Apple」と表示されます。

○iteratorを使った走査

複数の要素を順番に読み取る場合、iteratorを使用する方法もあります。

iteratorはJavaのコレクションフレームワークで提供されているインターフェースで、ArrayListを含む多くのコレクションクラスで利用可能です。

import java.util.ArrayList;
import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        Iterator<String> iterator = fruits.iterator();  // イテレータを取得
        while (iterator.hasNext()) {
            String fruit = iterator.next();  // 次の要素を取得
            System.out.println("取得した要素: " + fruit);
        }
    }
}

このコードでは、最初に「Apple」と「Banana」を含むArrayListを作成しています。

次に、そのArrayListからiteratorオブジェクトを取得し、そのiteratorを使って要素を順に読み取っています。

このコードを実行すると、コンソールに「取得した要素: Apple」と「取得した要素: Banana」と表示されます。

□サンプルコード4:要素の読み取り

以上の2つの方法を組み合わせた下記のコードでは、getメソッドとiteratorを用いて同じArrayListから要素を読み取っています。

import java.util.ArrayList;
import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");

        // getメソッドでの読み取り
        String firstFruit = fruits.get(0);
        System.out.println("getメソッドで取得した要素: " + firstFruit);

        // iteratorでの読み取り
        Iterator<String> iterator = fruits.iterator();
        System.out.print("iteratorで取得した要素: ");
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
    }
}

このコードを実行すると、コンソールに「getメソッドで取得した要素: Apple」と「iteratorで取得した要素: Apple Banana」と表示されます。

このように、要素の読み取り方は目的や状況に応じて最適な方法を選ぶことができます。

getメソッドは特定の要素に瞬時にアクセスする際に便利ですが、要素を順番に処理する場合はiteratorが一般的に使用されます。

●ArrayListの要素を更新する方法

ArrayListでのデータ管理においては、要素の更新もよく行われる操作です。

特定のインデックスにある要素を新しい値で上書きするケースが多いでしょう。

要素を更新する主な手段としてはsetメソッドがあります。

○setメソッド

setメソッドは、指定されたインデックスの位置にある要素を新しい要素で置き換えます。

このメソッドは元の要素を新しい要素で上書きするため、元の要素は失われます。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");

        // インデックス0の要素を"Cherry"に更新
        fruits.set(0, "Cherry");

        // 更新後のArrayListを出力
        System.out.println("更新後のArrayList: " + fruits);
    }
}

上記のサンプルコードでは、最初に”Apple”と”Banana”が格納されたArrayListを作成しています。

次にsetメソッドを用いて、インデックス0の位置にある”Apple”を”Cherry”で上書きしています。

このコードを実行すると、コンソールに更新後のArrayList: [Cherry, Banana]と表示されます。

□サンプルコード5:要素の更新

setメソッド以外にも、インデックスを指定して既存の要素を更新する方法がいくつかあります。

例えば、removeメソッドとaddメソッドを組み合わせることもできます。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");

        // インデックス0の要素を削除
        fruits.remove(0);

        // インデックス0に"Cherry"を挿入
        fruits.add(0, "Cherry");

        // 更新後のArrayListを出力
        System.out.println("別の方法で更新後のArrayList: " + fruits);
    }
}

このコードでは、最初にインデックス0の”Apple”をremoveメソッドで削除しています。

その後、addメソッドでインデックス0に新しい要素”Cherry”を挿入しています。

この場合も、コードを実行すると、コンソールに別の方法で更新後のArrayList: [Cherry, Banana]と表示されます。

このようにsetメソッドは直感的で簡単に要素を更新できますが、元の要素の位置関係を保ちつつ新しい要素を挿入したい場合には、removeaddの組み合わせも有効です。

●ArrayListをソートする方法

リスト内の要素を特定の順序で並び替える、いわゆるソート操作は、データ処理で非常によく使われます。

JavaのArrayListも例外ではなく、特定のメソッドやクラスを使用して簡単にソートできます。

○Collections.sortメソッド

Javaの標準ライブラリに含まれるCollectionsクラスのsortメソッドは、リスト型のデータを破壊的にソートします。

破壊的とは、元のリストのデータ自体が変更されることを意味します。

このsortメソッドは、特にパラメータが与えられない場合、自然順序付けに基づいてソートを行います。

import java.util.ArrayList;
import java.util.Collections;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();
        numbers.add(30);
        numbers.add(10);
        numbers.add(20);

        // ソートの実行
        Collections.sort(numbers);

        // ソート後のArrayListを出力
        System.out.println("ソート後のArrayList: " + numbers);
    }
}

上記のコードでは、ArrayList<Integer>型のnumbersリストを作成し、その中に30、10、20という3つの要素を追加しています。

その後、Collections.sortメソッドを使用して、このリストをソートしています。

ソートが完了すると、リストnumbersは[10, 20, 30]という順番になります。

□サンプルコード6:ArrayListのソート

自然順序付け以外にも、独自の比較ルールに基づいてソートを行いたい場合もあります。

その際には、Comparatorインターフェースを実装したクラスを作成し、そのインスタンスをCollections.sortメソッドの第二引数として渡します。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();
        numbers.add(30);
        numbers.add(10);
        numbers.add(20);

        // 降順でソートするためのComparator を定義
        Comparator<Integer> descComparator = new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        };

        // 降順でソート
        Collections.sort(numbers, descComparator);

        // ソート後のArrayListを出力
        System.out.println("降順でソート後のArrayList: " + numbers);
    }
}

このコードでは、descComparatorという名前でComparator<Integer>型の匿名クラスを作成しています。

compareメソッド内で降順にソートするための比較処理を実装しています。

このdescComparatorCollections.sortメソッドの第二引数として渡すことで、numbersリストは降順、すなわち[30, 20, 10]という順番にソートされます。

●ArrayListのサイズを確認する方法

プログラミングでデータを扱う際、データ構造のサイズを確認することは一般的な要件と言えます。

JavaでのArrayListにおいても、そのサイズを知ることは多くの場合において役立ちます。

具体的な使用ケースとしては、ループ処理でArrayListのすべての要素にアクセスする際や、ArrayListに新しい要素を追加する前に現在の容量を確認するなどがあります。

○sizeメソッド

ArrayListのサイズを確認する最も直接的な方法はsizeメソッドを使用することです。

このメソッドはArrayListの要素数を返すため、リストが空であれば0を返します。

ここで一つのサンプルコードを見てみましょう。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");

        // ArrayListのサイズを確認
        int size = fruits.size();

        // 確認したサイズを出力
        System.out.println("ArrayListのサイズ: " + size);
    }
}

このコードでは、ArrayList<String>型のfruitsという名前のリストを作成しています。

このリストには”Apple”、”Banana”、”Cherry”という3つの文字列要素が追加されています。

sizeメソッドを用いてArrayListのサイズを取得し、その値をsize変数に格納しています。

最後にそのサイズを出力しています。

このコードを実行すると、コンソールにはArrayListのサイズ: 3と表示されます。

□サンプルコード7:ArrayListのサイズ確認

サイズが0であるかどうかを確認することで、ArrayListが空であるかどうかも判定できます。

そのようなケースを考慮に入れたサンプルコードを紹介します。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();

        // ArrayListが空であるか確認
        if (fruits.size() == 0) {
            System.out.println("ArrayListは空です。");
        } else {
            System.out.println("ArrayListには要素が含まれています。");
        }
    }
}

このコードを実行すると、「ArrayListは空です。」というメッセージが出力されます。

なぜなら、fruitsリストには何も追加されていないため、そのサイズは0になるからです。

●ArrayListの応用例

JavaにおけるArrayListは多用されるデータ構造であり、その用途は基本的なリスト操作から高度なデータ処理まで多岐にわたります。

それでは、ArrayListの応用例としてデータフィルタリング、データ集計、そしてStream APIとの連携について説明します。

○ArrayListを使ったデータのフィルタリング

特定の条件に合致する要素だけを取り出す場合、ArrayListは非常に役立ちます。

具体的な方法としては、for-eachループやIteratorを使って元のArrayListから条件に合致する要素だけを新しいArrayListに格納するという手法があります。

□サンプルコード8:データフィルタリング

import java.util.ArrayList;
import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();
        // 1から10までの数字を追加
        for(int i = 1; i <= 10; i++) {
            numbers.add(i);
        }

        // 偶数だけを格納する新しいArrayListを作成
        ArrayList<Integer> evenNumbers = new ArrayList<>();
        for(Integer num : numbers) {
            if(num % 2 == 0) {
                evenNumbers.add(num);
            }
        }

        // 結果を出力
        System.out.println(evenNumbers);
    }
}

このコードでは1から10までの整数を含むArrayListを作成しています。

その後、偶数のみを格納する新しいArrayList(evenNumbers)を作成しています。

この新しいリストには、元のnumbersリストから偶数だけが格納されます。

コードを実行すると、[2, 4, 6, 8, 10]というArrayListが出力されます。

○ArrayListを使ったデータの集計

次に、ArrayList内のデータを集計する例について説明します。

例えば、Integer型のArrayListがある場合、その要素の合計や平均を求めることができます。

□サンプルコード9:データ集計

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> scores = new ArrayList<>();
        scores.add(90);
        scores.add(85);
        scores.add(77);
        scores.add(95);

        int sum = 0;
        for(Integer score : scores) {
            sum += score;
        }

        double average = (double) sum / scores.size();
        System.out.println("合計点: " + sum);
        System.out.println("平均点: " + average);
    }
}

このサンプルコードでは、ArrayListに格納されている数値(この場合は試験の点数)を合計して平均を出しています。

このようにしてscoresから合計点と平均点を計算することができます。

コードを実行すると、”合計点: 347″と”平均点: 86.75″が出力されます。

○ArrayListとStream API

Java 8以降、Stream APIを用いると、ArrayListの操作が一層効率的になります。

特に、フィルタリングや集計において便利な機能が多数提供されています。

□サンプルコード10:Stream APIとの連携

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();
        for(int i = 1; i <= 10; i++) {
            numbers.add(i);
        }

        // Streamを使用して偶数だけを取り出し、新しいリストに格納
        List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());

        // 結果を出力
        System.out.println(evenNumbers);
    }
}

このコードは、最初に1から10までの整数が格納されたArrayListを作成します。

その後、Stream APIを使用して偶数だけを取り出し、新しいリストに格納しています。

最後に、その新しいリストを出力しています。

実行結果として[2, 4, 6, 8, 10]というArrayListが出力されます。

●注意点と対処法

ArrayListは便利である一方で、注意が必要な点もあります。

それでは、特に注意すべき2点、null要素の取り扱いとスレッドセーフについて詳しく説明します。

○null要素の取り扱い

ArrayListはnull要素を許容するため、操作を行う際にNullPointerExceptionを引き起こす可能性があります。

例えば、getメソッドでnullを取得し、その後でその要素のメソッドを呼び出すと、NullPointerExceptionが発生します。

このような問題を防ぐ一つの方法は、要素を操作する前にnullチェックを行うことです。

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("apple");
        list.add(null);
        list.add("orange");

        for(String item : list) {
            // nullチェックを行う
            if(item != null) {
                // 大文字に変換して出力
                System.out.println(item.toUpperCase());
            } else {
                // nullの場合はその旨を出力
                System.out.println("この要素はnullです。");
            }
        }
    }
}

このコードでは、ArrayListに”apple”、null、”orange”という3つの要素を追加しています。

そして、各要素に対してnullチェックを行った後で、大文字に変換して出力しています。

この結果、「APPLE」、「この要素はnullです。」、「ORANGE」という出力が得られます。

○スレッドセーフについて

基本的なArrayListはスレッドセーフではありません。

そのため、複数のスレッドから同時にArrayListにアクセスする場面では問題が生じる可能性があります。

これを解決するためには、CollectionsクラスのsynchronizedListメソッドを用いてスレッドセーフなリストを生成することが一般的です。

□サンプルコード11:スレッドセーフなArrayListの作成

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // 通常のArrayList
        ArrayList<String> normalList = new ArrayList<>();
        normalList.add("apple");
        normalList.add("banana");
        normalList.add("cherry");

        // スレッドセーフなArrayListを生成
        List<String> synchronizedList = Collections.synchronizedList(normalList);

        // スレッドセーフなリストに新しい要素を追加
        synchronized (synchronizedList) {
            synchronizedList.add("date");
        }

        // 結果を出力
        synchronized (synchronizedList) {
            for(String item : synchronizedList) {
                System.out.println(item);
            }
        }
    }
}

このコードでは、まず通常のArrayListを作成しています。

その後、CollectionsクラスのsynchronizedListメソッドを用いて、スレッドセーフなArrayListを生成しています。

このArrayListに新しい要素を追加したり、その内容を出力する際には、synchronizedブロックを用いて排他制御を行っています。

実行すると、”apple”、”banana”、”cherry”、”date”が順に出力されます。

●カスタマイズ方法

ArrayListを一歩進めて使うためには、カスタムクラスを要素とする方法があります。

基本型やJavaが提供するクラスだけでなく、自分で定義したクラスをArrayListの要素として使用することで、より複雑なデータ構造を簡単に扱うことができます。

○カスタムクラスを要素とするArrayList

Javaでオブジェクト指向プログラミングを行う際、自分自身でクラスを定義して、そのインスタンスをArrayListで管理するケースは多いです。

たとえば、”Person”というクラスがあり、その属性(名前、年齢など)をArrayListで一括管理したい場合、カスタムクラスを要素とするArrayListを使います。

□サンプルコード12:カスタムクラスを使ったArrayList

import java.util.ArrayList;

// Person クラスの定義
class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

public class Main {
    public static void main(String[] args) {
        // Person クラスのオブジェクトを要素とするArrayListの作成
        ArrayList<Person> personList = new ArrayList<>();

        // Person オブジェクトを作成して追加
        personList.add(new Person("Alice", 30));
        personList.add(new Person("Bob", 40));
        personList.add(new Person("Charlie", 50));

        // ArrayList内の要素を出力
        for (Person person : personList) {
            System.out.println(person);
        }
    }
}

このサンプルコードでは、まず「Person」という名前のカスタムクラスを定義しています。

このクラスには「name」と「age」という二つのフィールドがあります。

そして、その後でこの「Person」クラスのオブジェクトを要素とするArrayList(personList)を作成しています。

このArrayListには、Alice(30歳)、Bob(40歳)、Charlie(50歳)の3つのPersonオブジェクトを追加しています。

最後に、ArrayList内の各要素(Personオブジェクト)を出力しています。

このプログラムを実行すると、次のようにコンソールに表示されます。

Person{name='Alice', age=30}
Person{name='Bob', age=40}
Person{name='Charlie', age=50}

まとめ

JavaのArrayListは、動的な配列を扱う際に非常に便利なデータ構造です。

この記事で取り上げた要点は、ArrayListの使い方の基本から、要素の追加、削除、更新、そして読み取り方法、さらにはソートやサイズ確認まで多岐にわたります。

この記事が、あなたのプログラミング学習や仕事における具体的な課題解決に少しでも貢献できれば幸いです。

今後も、より高度なプログラミングテクニックをマスターするための学習を続けましょう。