102 「Map修羅道」 Step03 解答例

MapUtil.java

import java.util.*;

public class MapUtil {
    public static void printCategoryMap() {
        // Mapを作成。キーがカテゴリ(String)、値が商品名リスト(List<String>)
        Map<String, List<String>> categoryMap = new HashMap<>();

        // 商品を追加するユーティリティ処理
        // カテゴリがMapに存在しなければ新しくListを作る
        // すでに存在すれば、そのListに追加する

        addProduct(categoryMap, "Food", "Apple");
        addProduct(categoryMap, "Food", "Banana");
        addProduct(categoryMap, "Clothing", "T-shirt");
        addProduct(categoryMap, "Clothing", "Jeans");
        addProduct(categoryMap, "Food", "Orange");  // 既存のFoodカテゴリに追加

        // 出力:カテゴリごとに商品一覧を表示
        for (String category : categoryMap.keySet()) {
            System.out.println(category + ":");
            for (String product : categoryMap.get(category)) {
                System.out.println("  - " + product);
            }
        }
    }

    // 商品をカテゴリに追加するメソッド(Mapの値がListなので工夫が必要)
    private static void addProduct(Map<String, List<String>> map, String category, String product) {
        // すでにそのカテゴリがあるかチェック
        if (!map.containsKey(category)) {
            // なければ新しいリストを作成し、Mapにputする
            map.put(category, new ArrayList<>());
        }
        // カテゴリに対応するリストに商品を追加
        map.get(category).add(product);
    }
}

解説:Mapに複数の値を格納したいときは List を使え

なぜ Map<String, List<String>> が必要なのか?

JavaのMapは「1つのキーに1つの値」が原則です。
しかし「カテゴリ → 複数の商品」のように、1対多の関係を扱いたい場面では、
値としてListやSetなどのコレクションを使うのが一般的です。


実装のポイント:キーの存在確認とListの初期化

新しい商品を追加するたびに、以下の手順が必要になります:

  1. そのカテゴリ(キー)がMapに存在するか確認
  2. 存在しなければ、new ArrayList<>(); で初期化して put()
  3. そのリストに .add() で商品を追加
if (!map.containsKey(category)) {
    map.put(category, new ArrayList<>());
}
map.get(category).add(product);

この処理はよくあるため、ユーティリティメソッドにまとめて再利用するのがベストです。


出力の工夫

カテゴリ → 商品リストを表示するには、次のような二重ループになります:

for (String category : map.keySet()) {
    System.out.println(category + ":");
    for (String product : map.get(category)) {
        System.out.println("  - " + product);
    }
}

実行結果の例(順不同):

Food:
  - Apple
  - Banana
  - Orange
Clothing:
  - T-shirt
  - Jeans

まとめ:このステップで学ぶべきこと

  • Map<String, List<String>> という構造
  • 1つのキーに複数の値を関連付ける設計方法
  • containsKey() での存在チェックと初期化
  • 二重ループによる出力処理

このステップを乗り越えれば、Mapを使った柔軟なデータ構造の基礎が身につきます。

102 ステップアップ問題 「Map修羅道」

Just Keep Typing, Baby!では、この「Map修羅道」でつまづいた人向けの解説をしています。こちらもぜひ!