1. 導入
私たちはすでに、ArrayList は自動的に伸びる「動的配列」であることを知っています。ただし1つ制約があります。要素へのアクセスは番号(インデックス)によります。千人分のリストがあり、アリスの電話番号を探したい場合、彼女のインデックスを知っているか、全員を順番に走査する必要があります。
実生活では、私たちはしばしば一意な手がかりでデータを探します:
- 名前から電話番号を探す、
- パスポート番号から所有者を探す、
- ログイン名からパスワードを見つける、
- ID でデータベースのオブジェクトを探す。
そのためには「キーを受け取ったら → すぐに値が見つかる」構造が必要です。Java ではこれを HashMap<K,V> が担います。
たとえ話:
紙の辞書を想像してください。単語「house」の訳を探すとき、最初からすべてのページをめくる必要はありません。すぐに H のページへ行き、目的の単語を見つけます。HashMap も同じです。キー(単語)から瞬時に値(訳)を取り出せます。
辞書の作成
辞書を作成するには、キーと値がどの型かを指定します。
import java.util.HashMap;
HashMap<String, String> phonebook = new HashMap<String, String>();
ここでは:
- String(1番目の型)はキーの型(人の名前)です。
- String(2番目の型)は値の型(電話番号)です。
これで phonebook は本物の電話帳のようなものです.
その他の例:
HashMap<String, Integer> grades = new HashMap<String, Integer>(); // 名前 → 評価
HashMap<Integer, String> users = new HashMap<Integer, String>(); // ID → 名前
HashMap<String, Boolean> flags = new HashMap<String, Boolean>(); // キー → 論理値
ArrayList と違って、辞書には add() はありませんが、代わりに便利なメソッドが揃っています。
2. メソッド put(key, value) — ペアを追加
HashMap の最大の違いは、単なる値の集まりではなく、キーと値のペアを保存する点にあります。これはまさに辞書のように、各単語に訳があり、各名前に電話番号がある、というイメージです。
例:
phonebook.put("アリス", "+380501112233");
phonebook.put("ボブ", "+380671234567");
これで電話帳は次のとおりです:
- キー 「アリス」 は値 「+10501112233」 に対応しています。
- キー 「ボブ」 は値 「+10671234567」 に対応しています。
つまり、値(電話番号)を得るには、キー(名前)さえ分かっていればよいということです。
重要: キーは一意です。既存のキーに対して新しい値を追加しようとすると、古い値は上書きされます。
phonebook.put("アリス", "+10999999999");
これでアリスには新しい番号だけが残り、古い番号は失われます。
まとめ: put は追加または更新のためのメソッドです。新しいキーなら新規作成、既存のキーなら更新が行われます。
3. メソッド get(key) — 値を取得
値を見つけるにはキーを知っている必要があります。これこそが HashMap の強みで、キー検索は非常に高速です。レコードが千件でも百万件でも、ほぼ瞬時に見つかります。
例:
System.out.println(phonebook.get("アリス"));
出力:
+10501112233
そのキーが存在しない場合、get は null を返します:
System.out.println(phonebook.get("チャーリー")); // null
つまり「キー 「チャーリー」 は辞書に存在しない」ということです。
4. メソッド containsKey(key) — 存在確認
null を避けるには、まずそのキーが辞書にあるかどうかを確認すると便利です。
例:
System.out.println(phonebook.containsKey("チャーリー"));
出力:
false
これで事前に判断できます:
- キーがないなら — 新しいレコードを作成する、
- キーがあるなら — 既存レコードを更新する。
よくあるパターン:
if (phonebook.containsKey("アリス"))
{
System.out.println("アリスの番号はすでに登録されています!");
}
else
{
phonebook.put("アリス", "+10111111111");
}
5. メソッド remove(key) — レコードを削除
削除も同様に簡単で、必要なのはキーだけです。
phonebook.remove("ボブ");
System.out.println(phonebook.get("ボブ"));
出力:
null
これでキー 「ボブ」 のレコードは辞書に存在しません。
6. すべてのペアを走査する
特定のキーだけでなく、辞書全体を出力したいこともよくあります。その場合は entrySet() を使います。
for (var entry : phonebook.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
出力例:
アリス -> +10501112233
このように、キー(entry.getKey())と値(entry.getValue())の両方に同時にアクセスできます。
7. 実践: 語数カウント
テキスト中の単語の出現回数を数えるという古典的な問題を見てみましょう。これは HashMap の用途を理解するのに最適な例です。
String text = "java java core java";
HashMap<String, Integer> freq = new HashMap<String, Integer>();
for (String w : text.split(" "))
{
Integer old = freq.get(w);
freq.put(w, (old == null) ? 1 : old + 1);
}
System.out.println(freq);
出力:
{core=1, java=3}
ここで何が起きているか、順に見ていきます:
- 文字列 "java java core java" を単語に分割します。
- 各単語について、すでに辞書にあるかどうかを確認します(freq.get(w))。
- なければ(null)、その単語の初出なので 1 を入れます。
- あれば、その単語は既出なので値を 1 増やします。
実用例:
- API への呼び出し回数のカウント、
- テキスト中の単語頻度の統計、
- 在庫数の管理。
8. 実践: 電話帳
もう少し大きいアプリを書いてみましょう。
import java.util.HashMap;
import java.util.Scanner;
public class PhonebookApp {
public static void main(String[] args)
{
HashMap<String, String> phonebook = new HashMap<String, String>();
Scanner console = new Scanner(System.in);
while (true)
{
System.out.print("名前を入力してください(空行で終了): ");
String name = console.nextLine();
if (name.isEmpty()) break;
System.out.print("番号を入力してください: ");
String phone = console.nextLine();
phonebook.put(name, phone);
}
System.out.println("電話帳:");
for (var entry : phonebook.entrySet())
{
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
}
}
このプログラムは小さなリファレンス帳のように動作します。名前と電話番号を入力すると、それらが HashMap に保存されます。最後に一覧を出力できます。辞書(マップ)は実際のプロジェクトでも非常に頻繁に使われます。
GO TO FULL VERSION