Java Tips | コレクション:空Map安全取得

Java Java
スポンサーリンク

空Map安全取得は「null を“空の設定”にそろえる」ための小さな約束

Map を返すメソッドも、業務コードに山ほど出てきます。
設定値のマップ、コード→ラベルのマップ、集計結果のマップなど。

そこでよく起きるのが、このパターンです。

Map<String, String> settings = loadSettings();
if (settings != null) {
    String value = settings.get("timeout");
    ...
}
Java

毎回 settings != null を書いていると、どこかで必ず書き忘れます。
そして、NullPointerException が飛ぶ。

空Map安全取得は、ここを「そもそも null を返さない世界」に変えるためのユーティリティです。
「null かもしれない Map」を、「必ず空か要素ありの Map」に正規化するイメージです。


基本アイデア:null なら空Mapに変換する

emptyIfNull という“正規化関数”を用意する

まずは、どんな Map が来ても「null なら空Mapにする」メソッドを用意します。

import java.util.Collections;
import java.util.Map;

public final class MapUtils {

    private MapUtils() {}

    public static <K, V> Map<K, V> emptyIfNull(Map<K, V> map) {
        return (map == null) ? Collections.emptyMap() : map;
    }
}
Java

使い方はとてもシンプルです。

Map<String, String> raw = null;

Map<String, String> safe = MapUtils.emptyIfNull(raw);
System.out.println(safe.size());      // 0
String value = safe.get("timeout");   // nullチェック不要
Java

ここで重要なのは、次の2点です。

一つ目は、「呼び出し側が null を意識しなくてよくなる」ことです。
emptyIfNull を通した時点で、「この Map は null ではない」と保証されるので、
map.get(...)map.entrySet() も安心して呼べます。

二つ目は、「null と“キーが一つもない状態”を同じ扱いにする」という設計を、
ユーティリティに閉じ込めていることです。
「該当なし=空Map」というルールを徹底すると、
コード全体の分岐がかなり減ります。


呼び出し側のコードがどう変わるかを比べてみる

before:毎回 null チェックが必要な世界

従来の書き方だと、こうなりがちです。

Map<String, String> settings = loadSettings();

if (settings != null && !settings.isEmpty()) {
    String timeout = settings.get("timeout");
    ...
}
Java

settings != null を書き忘れると NPE。
isEmpty() を書き忘れると、無駄な処理や想定外の挙動。

after:空Map安全取得を使った世界

空Map安全取得を挟むと、こう書けます。

Map<String, String> settings = MapUtils.emptyIfNull(loadSettings());

String timeout = settings.get("timeout");
...
Java

「null かもしれない」という不安を、
emptyIfNull の中に押し込めてしまったイメージです。

ここで深掘りしたいポイントは、「null チェックの責任の場所を変えている」ということです。
今までは「呼び出し側が毎回責任を負っていた」のを、
「ユーティリティが一度だけ責任を負う」形に変えています。


戻り値側で「最初から空Mapを返す」設計にする

そもそも null を返さないメソッドにする

もっと理想を言えば、
「Map を返すメソッドは、null ではなく空Mapを返す」
というルールにしてしまうのがベストです。

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SettingsRepository {

    public Map<String, String> loadSettings() {
        Map<String, String> result = ...; // DBやファイルから取得
        if (result == null || result.isEmpty()) {
            return Collections.emptyMap();
        }
        return result;
    }
}
Java

こうしておけば、呼び出し側は emptyIfNull すら要りません。

Map<String, String> settings = settingsRepository.loadSettings();
String timeout = settings.get("timeout");
Java

ここでの重要ポイントは、「null を返すかどうかは“設計の約束事”」だということです。
「このプロジェクトでは、コレクションの戻り値に null は使わない」
と決めてしまえば、空Map安全取得は「外部ライブラリや古いコードと接続するとき」だけに使えばよくなります。


Collections.emptyMap() と new HashMap<>() の違いも押さえておく

どちらも「空」だが、性質が違う

空Mapを返すとき、よく使うのがこの2つです。

Collections.emptyMap(); // 不変(変更不可)の空Map
new HashMap<>();        // 変更可能な空Map
Java

空Map安全取得では、基本的に Collections.emptyMap() を使うのがおすすめです。

理由は二つあります。

一つ目は、「共有しても問題ないから」です。
Collections.emptyMap() は中身が変わらないので、
どこに渡しても安全です。

二つ目は、「“ここでは追加しない前提”がはっきりするから」です。
emptyIfNull の戻り値に対して put しようとすると例外になるので、
「ここで追加するのは設計ミスだ」とすぐに気づけます。

Map<String, String> safe = MapUtils.emptyIfNull(null);
safe.put("x", "1"); // UnsupportedOperationException
Java

もし「呼び出し側で put したい」ケースなら、
emptyIfNull の後で明示的に new HashMap<>(safe) すればよい、
という分離ができます。


実務での「空Map安全取得」の使いどころ

外部ライブラリや古いコードとつなぐときの“防波堤”

外部ライブラリや、昔の自前コードは、
平気で「該当なしなら null を返す」メソッドを持っていたりします。

そういうメソッドを直接使うのではなく、
必ず空Map安全取得を挟むようにすると、安全な境界線を引けます。

Map<String, String> raw = legacyApi.getSettings();      // null かもしれない
Map<String, String> settings = MapUtils.emptyIfNull(raw); // ここから先は null ではない世界
Java

この「境界で正規化する」という考え方は、
業務システム全体の安定性を上げるうえで、とても大事な感覚です。


まとめ:空Map安全取得で身につけてほしい感覚

空Map安全取得は、単に「NPE を避ける小技」ではなく、
「null を“空の設定”にそろえて、世界をシンプルにする」 ためのユーティリティです。

null なら Collections.emptyMap() を返す emptyIfNull を用意する。
Map を返すメソッドは、原則として null ではなく空Mapを返す設計にする。
空Mapには不変のもの(Collections.emptyMap())を使い、「ここでは追加しない前提」を明確にする。
外部や古いコードとの境界で「null → 空Map」に正規化し、内側の世界をシンプルに保つ。

もしあなたのコードのどこかに、

Map<String, String> m = xxx();
if (m != null) {
    ...
}
Java

というパターンが何度も出てきているなら、
それを一度「空Map安全取得+空Mapを返す設計」に置き換えられないか、眺めてみてください。

その小さな整理が、
「null に振り回されない、安定したコレクション処理を書けるエンジニア」への、
確かな一歩になります。

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