CodeGym /課程 /JAVA 25 SELF /「自訂字典」 — HashMap<K,V>...

「自訂字典」 — HashMap<K,V>

JAVA 25 SELF
等級 12 , 課堂 2
開放

1. 前言

我們已經知道,ArrayList 是一個會自己成長的「無限陣列」。但它有個限制:只能透過編號(索引)來存取元素。如果有一份包含一千人的清單,而我們想找到 Alice 的電話,就必須不是已知她的索引,就是得把所有人逐一遍歷。

在現實中,我們常常依據唯一的特徵來查找資料:

  • 依姓名找電話號碼,
  • 依護照號碼找持有人,
  • 依登入名找到密碼,
  • 依 id 在資料庫中尋找物件。

因此我們需要一種結構,能夠「拿到鍵 → 立刻找到值」。在 Java 中這就是 HashMap<K,V> 的職責。

類比:
請想像一本紙本字典。你要查單字「house」的翻譯,不需要一頁頁翻。你會直接翻到字母「H」,然後找到對應的單字。HashMap 也是如此:依鍵(單字)就能瞬間取得值(翻譯)。

建立字典

要建立字典,必須指定哪些型別作為

import java.util.HashMap;

HashMap<String, String> phonebook = new HashMap<String, String>();

說明:

  • String(第一個型別)是鍵的型別(人的姓名)。
  • String(第二個型別)是值的型別(電話號碼)。

現在 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("Alice", "+380501112233");
phonebook.put("Bob", "+380671234567");

現在在我們的電話簿中:

  • "Alice" 對應值 "+10501112233"
  • "Bob" 對應值 "+10671234567"

這表示要取得值(電話),只要知道鍵(姓名)就行。

重要:鍵是唯一的。如果嘗試以已存在的鍵加入新值,舊的值會被覆寫。

phonebook.put("Alice", "+10999999999");

現在 Alice 只剩下新號碼;舊號碼已經被覆蓋了。

結論:put 是用來新增或更新紀錄的方法。鍵是新的—就建立紀錄;鍵已存在—就更新紀錄。

3. 方法 get(key) — 取得值

要找到值,需要知道鍵。這正是 HashMap 的關鍵:依鍵查找非常快,幾乎是瞬間,無論我們有一千筆或一百萬筆資料。

範例:

System.out.println(phonebook.get("Alice"));

輸出:

+10501112233

如果沒有該鍵,get 會回傳 null

System.out.println(phonebook.get("Charlie")); // null

這表示:「字典中沒有鍵 'Charlie'」。

4. 方法 containsKey(key) — 檢查是否存在

為了避免遇到 null,先檢查字典是否包含該鍵會很有幫助。

範例:

System.out.println(phonebook.containsKey("Charlie"));

輸出:

false

因此我們可以事先判斷:

  • 若沒有該鍵——建立新紀錄,
  • 若已有該鍵——更新紀錄。

常見寫法:

if (phonebook.containsKey("Alice")) 
{
    System.out.println("Alice 已經有號碼了!");
} 
else 
{
    phonebook.put("Alice", "+10111111111");
}

5. 方法 remove(key) — 刪除紀錄

刪除同樣很簡單:只需要知道鍵。

phonebook.remove("Bob");
System.out.println(phonebook.get("Bob"));

輸出:

null

現在鍵為 "Bob" 的紀錄已不存在於字典中。

6. 遍歷所有配對

我們常常不只要根據特定鍵取得資料,也需要把整個字典列出。這時可以使用 entrySet() 方法。

for (var entry : phonebook.entrySet()) {
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}

範例輸出:

Alice -> +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}

詳細說明如下:

  1. 我們把字串 "java java core java" 依空白切成單字。
  2. 對於每個單字,檢查它是否已在字典中(freq.get(w))。
  3. 如果沒有(null),代表是第一次出現 → 放入 1
  4. 如果已存在,代表曾經出現過 → 將值加一。

實際用途:

  • 計算對 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 中。最後可以把整個清單列出。字典在真實專案中非常常見。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION