MapとHashMap
Mapはキーと値のペアのコレクションです。このレッスンでは、Mapの使用方法を学びます。
Mapインターフェースの特徴
| 特徴 | 説明 |
|---|---|
| キーと値のペア | 各要素にキーと値がある |
| キーは一意 | キーは一意、値は重複可能 |
| 順序なし | HashMapは順序なし |
HashMap
HashMapは最も一般的に使用されるMap実装です。
HashMapの作成
JAVA
import java.util.HashMap;
import java.util.Map;
Map<String, Integer> map1 = new HashMap<>();
Map<String, Integer> map2 = new HashMap<>(100); // 指定容量
Map<String, Integer> map3 = new HashMap<>(map1); // 他のMapから作成
基本操作
JAVA
import java.util.HashMap;
import java.util.Map;
public class HashMapDemo {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
// キーと値のペアを追加
scores.put("Alice", 95);
scores.put("Bob", 88);
scores.put("Charlie", 92);
System.out.println("Map: " + scores);
// 値を取得
int aliceScore = scores.get("Alice");
System.out.println("Aliceのスコア: " + aliceScore);
// 値を取得(キーが存在しない場合にデフォルト値を返す)
int davidScore = scores.getOrDefault("David", 0);
System.out.println("Davidのスコア: " + davidScore);
// チェック
System.out.println("Aliceを含む: " + scores.containsKey("Alice"));
System.out.println("95を含む: " + scores.containsValue(95));
System.out.println("サイズ: " + scores.size());
// 変更
scores.put("Alice", 98); // 古い値を上書き
System.out.println("更新後のAlice: " + scores.get("Alice"));
// 削除
scores.remove("Bob");
System.out.println("削除後: " + scores);
}
}
putIfAbsent
JAVA
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 95);
// キーが存在しない場合にのみ追加
map.putIfAbsent("Alice", 100); // 上書きされない
map.putIfAbsent("Bob", 88); // 追加される
System.out.println(map); // {Alice=95, Bob=88}
走査方法
方法1:keySetを走査
JAVA
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 95);
map.put("Bob", 88);
map.put("Charlie", 92);
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
方法2:valuesを走査
JAVA
for (int value : map.values()) {
System.out.println(value);
}
方法3:entrySetを走査
JAVA
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
方法4:Lambda
JAVA
map.forEach((key, value) -> System.out.println(key + ": " + value));
例:Mapの走査
JAVA
import java.util.HashMap;
import java.util.Map;
public class MapTraversal {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob", 88);
scores.put("Charlie", 92);
// entrySetで走査
System.out.println("=== entrySet走査 ===");
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// Lambdaで走査
System.out.println("=== Lambda走査 ===");
scores.forEach((name, score) ->
System.out.println(name + "のスコアは" + score));
}
}
TreeMap
TreeMapは赤黒木ベースで、キーが自動的にソートされます。
例:TreeMap
JAVA
import java.util.Map;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new TreeMap<>();
map.put("Charlie", 92);
map.put("Alice", 95);
map.put("Bob", 88);
// キーでソート
map.forEach((key, value) ->
System.out.println(key + ": " + value));
// Alice: 95
// Bob: 88
// Charlie: 92
}
}
LinkedHashMap
LinkedHashMapは挿入順序を維持します。
例:LinkedHashMap
JAVA
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDemo {
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<>();
map.put("Charlie", 92);
map.put("Alice", 95);
map.put("Bob", 88);
// 挿入順序
map.forEach((key, value) ->
System.out.println(key + ": " + value));
// Charlie: 92
// Alice: 95
// Bob: 88
}
}
一般的なMapメソッド
| メソッド | 説明 |
|---|---|
put(K, V) |
キーと値のペアを追加 |
get(K) |
値を取得 |
getOrDefault(K, V) |
値を取得、存在しない場合はデフォルト値 |
putIfAbsent(K, V) |
キーが存在しない場合に追加 |
remove(K) |
キーと値のペアを削除 |
containsKey(K) |
キーを含むか |
containsValue(V) |
値を含むか |
keySet() |
すべてのキーをSetとして取得 |
values() |
すべての値をCollectionとして取得 |
entrySet() |
すべてのエントリをSetとして取得 |
size() |
サイズ |
isEmpty() |
空かどうか |
clear() |
すべてクリア |
putAll(Map) |
すべて追加 |
Mapの比較
| 特徴 | HashMap | TreeMap | LinkedHashMap |
|---|---|---|---|
| 順序 | 順序なし | ソート済み | 挿入順 |
| 実装 | ハッシュテーブル | 赤黒木 | リンクリスト + ハッシュテーブル |
| パフォーマンス | O(1) | O(log n) | O(1) |
| nullキー | 1つ許可 | 許可しない | 1つ許可 |
例:単語頻度カウンター
JAVA
import java.util.HashMap;
import java.util.Map;
public class WordCount {
public static Map<String, Integer> count(String text) {
Map<String, Integer> map = new HashMap<>();
String[] words = text.toLowerCase().split("\\s+");
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
return map;
}
public static void main(String[] args) {
String text = "hello world hello java world hello";
Map<String, Integer> counts = count(text);
counts.forEach((word, count) ->
System.out.println(word + ": " + count));
// hello: 3
// world: 2
// java: 1
}
}
例:グループ化
JAVA
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GroupBy {
public static Map<String, List<String>> groupByFirstChar(List<String> list) {
Map<String, List<String>> map = new HashMap<>();
for (String s : list) {
String key = s.substring(0, 1).toUpperCase();
map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
}
return map;
}
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
names.add("David");
names.add("Eve");
Map<String, List<String>> groups = groupByFirstChar(names);
groups.forEach((key, value) ->
System.out.println(key + ": " + value));
// A: [Alice]
// B: [Bob]
// C: [Charlie]
// D: [David]
// E: [Eve]
}
}
❓ よくある質問
Q HashMapのキーはnullにできますか?
A はい、nullキーは1つだけ許可されます。値は複数のnullを持つことができます。
Q HashMapは重複キーをどのように検出しますか?
A まずhashCodeを比較し、次にequalsを比較します。HashSetと同様です。
Q HashMapはスレッドセーフですか?
A いいえ。マルチスレッドシナリオにはConcurrentHashMapを使用してください。
📖 まとめ
- Mapはキーと値のペアのコレクションで、キーは一意
- HashMapは順序なし、TreeMapはソート済み、LinkedHashMapは挿入順を維持
- 走査方法:keySet/values/entrySet/Lambda
- 一般的なメソッド:put/get/remove/containsKey/forEach
📝 演習
- 単語頻度: 文字列内の各単語の出現回数をカウント
- グループ化: 学生を成績レベル(優秀/良好/及格/不及格)でグループ化
- キャッシュ: HashMapを使用して簡単なキャッシュを実装
次のレッスン
次のレッスンでは、ジェネリクスを学びます — Javaジェネリクスを理解します。



