【Java】List.of()にnullを渡すとどうなる?安全なリストの構築方法

Java 9から追加されたList.of()は、簡潔に不変リスト(immutable list)を作成できる便利なAPIです。しかし、使い方を間違えるとNullPointerExceptionを引き起こす落とし穴があります

本記事では、List.of()nullを渡した場合の挙動と、安全にリストを構築する方法について解説します。

List.of()にnullを渡すとどうなるか

以下のようにnullを含む値をList.of()に渡すと、実行時に例外が発生します。

String a = "hello";
String b = null;

List<String> list = List.of(a, b); // ← ここで例外が発生

実行結果:

Exception in thread "main" java.lang.NullPointerException
    at java.base/java.util.ImmutableCollections.listFromTrustedArray(...)

List.of()は「null非許容」です。これは公式ドキュメントにも明記されています。

List (Java SE 9 & JDK 9 )から引用

安全な方法1:Stream.of() + filter(Object::nonNull)

nullを除外してリストを構築したい場合は、Stream APIを使って次のように書けます:

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

String a = "hello";
String b = null;

List<String> list = Stream.of(a, b)
    .filter(Objects::nonNull)
    .collect(Collectors.toList()); // → ["hello"]

この方法ではnullを安全に取り除いたリストを作成できます。List.of()と異なり変更可能なリストになりますが、多くの場合は問題ありません。

安全な方法2:手動でnullチェックして追加

もっと素朴な方法として、以下のようにif文で追加するのも実用的です:

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

String a = "hello";
String b = null;

List<String> list = new ArrayList<>();
if (a != null) list.add(a);
if (b != null) list.add(b); // → ["hello"]

処理の過程でnullを記録・無視・ログ出力したい場合など、柔軟性があります。

nullを含める必要がある場合は?

どうしてもnullを含む必要がある場合は、List.of()を使うのではなく、通常のArrayListArrays.asList()を使いましょう。

List<String> list = Arrays.asList("hello", null); // OK

ただし、Arrays.asList()は固定サイズリストを返すため、要素の追加・削除はできない点に注意してください。

✅ まとめ

方法null許容リスト型備考
List.of(a, b)不変リストnullを含むと例外
Stream.of(a, b).filter(…).collect()可変リストnullを除外して簡潔に書ける
手動で if != null で追加可変リスト柔軟な制御が可能
Arrays.asList(…)固定サイズ要素の追加削除不可

Javaでnullを扱う場面はまだ多くあります。List.of()は便利ですが、nullは許容されない」という仕様を正しく理解した上で使い分けることが大切です

[Spring Boot]プロジェクトを作成する(Spring Initializr)

Spring Bootのプロジェクトの作成方法はいくつかありますが、本記事ではSpring Initializrを使って作成します。

Projectを選択する

執筆時点では「Gradle – Groovy」「Gradle – Kotolin」「Maven」から選択できます。使いたいものを選択してください。

ここでは「Gradle – Groovy」を選択しています。

Languageを選択する

執筆時点では「Java」「Kotolin」「Groovy」から選択できます。使いたいものを選択してください。

ここでは「Java」を選択しています。

Spring Bootのバージョンを選択する

Spring Bootのバージョンを選択してください。

ここでは「3.0.4」を選択しています。

Project Metadataを入力する

プロジェクトのメタデータを入力します。

内容はプロジェクトに合わせて設定してください。

Dependenciesを選択する

Dependenciesの選択は任意ですが、Webアプリケーションのプロジェクトを作成するので、Spring Webだけ追加しておきます。すでに使用するものが決まっている場合はそれも追加しておいてください。

プロジェクトをダウンロードする

GENERATEボタンをクリックしてプロジェクトをダウンロードしてください。

プロジェクトを展開・配置してIDEで開く

ではダウンロードしたプロジェクトを展開・配置して、IDEで開いてみましょう。ここではIntelliJ IDEA Ultimateを使用しています。

まずはダウンロードしたZIPファイルを展開し任意のフォルダに配置します。

$ unzip ~/Downloads/tutorial.zip -d ~/Workspace/

次にIDEでプロジェクトを開きます。

動作確認のためにアプリケーションを実行してみましょう。

アプリケーションが起動したらhttp://localhost:8080/にアクセスします。

Spring BootではMainメソッド持ったクラス以外何もないため、表示するページがなく、エラー画面が表示されますが、この画面が表示しているのであれば問題ありません。

[Java]ラムダ式を使ってコレクションを操作する(Java Lambda)

Java 8から導入されたラムダ式を使ってコレクションを操作する方法について解説します。ここでは、実用的なものに的を絞って解説しています。

前提(説明時に使用しているDTO)

説明で使用しているDTOを提示しておきます。ここではUserDtoクラスを使用しています。

import java.io.Serializable;

public class UserDto implements Serializable {
    private String userId;
    private String userName;
    private int age;

    // Setter, Getterは省略

    public String toString() {
        return "userId=" + userId + ",userName=" + userName + ",age=" + age;
    }

}

ListをMapに変換する

ListをMapに変換する方法について解説します。

以下の例では、UserDtoクラスを要素に持つListをMapに変換しています。MapのキーはUserDtoのuserId、値はUserDtoにしています。

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

public class Main {
    public static void main(String[] args) {
        // UserDtoを要素として持つListを用意する
        List<UserDto> list = new ArrayList<>();
        UserDto user1 = new UserDto();
        user1.setUserId("001");
        user1.setUserName("John Smith");
        user1.setAge(20);
        list.add(user1);
        UserDto user2 = new UserDto();
        user2.setUserId("002");
        user2.setUserName("Maria Cambell");
        user2.setAge(28);
        list.add(user2);
        
        // ListをMapに変換する(キーはUserDTOのUserIdを使用する)
        Map<String, UserDto> map = list.stream().collect(Collectors.toMap(s -> s.getUserId(), s -> s));

        // Listの出力結果を確認する
        System.out.println(list);
        // [userId=001,userName=John Smith,age=20,userId=002, userName=Maria Cambell,age=28]
        
        // 変換後のMapの出力結果を確認する
        System.out.println(map);
        // {001=userId=001,userName=John Smith,age=20, 002=userId=002,userName=Maria Cambell,age=28}
    }
}

Listから一部の項目を抽出する

Listから一部の項目を抽出する方法について解説します。

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

public class Main {
    public static void main(String[] args) {
        // UserDtoを要素として持つListを用意する
        List<UserDto> list = new ArrayList<>();
        UserDto user1 = new UserDto();
        user1.setUserId("001");
        user1.setUserName("John Smith");
        user1.setAge(20);
        list.add(user1);
        UserDto user2 = new UserDto();
        user2.setUserId("002");
        user2.setUserName("Maria Cambell");
        user2.setAge(28);
        list.add(user2);

        // Listから項目の一部(ここではUserDtoのuserIdを抽出)し、リストにする
        List<String> userIds = list.stream().map(s -> s.getUserId()).collect(Collectors.toList());
  
        
        // 抽出前のListの内容を確認する
        System.out.println(list);
        // [userId=001,userName=John Smith,age=20, userId=002,userName=Maria Cambell,age=28]
        // 抽出した項目を確認する
        System.out.println(userIds);
        // [001, 002]
    }
}
モバイルバージョンを終了