Hash Map
Terakhir diperbarui
Hash map adalah struktur data yang menyimpan pasangan key-value dan memungkinkanmu mencari sebuah nilai berdasarkan key-nya dalam O(1) secara rata-rata. Cara kerjanya persis seperti hash table, tetapi setiap entri di bucket membawa key sekaligus nilai yang terkait dengannya. Untuk menyimpan atau mengambil sebuah pasangan, key di-hash menjadi indeks bucket, lalu rantai di bucket itu dipindai untuk mencari key yang cocok. Tekan Putar di atas untuk melihat pasangan ditempatkan ke bucket hasil hash dan sebuah nilai diambil berdasarkan key-nya.
Inilah struktur di balik dict di Python, HashMap di Java, dan Map/objek di JavaScript. Tabrakan (collision) ditangani dengan cara yang sama seperti pada hash table, di sini dengan separate chaining, jadi performanya bergantung pada fungsi hash yang bagus dan load factor yang rendah.
Kompleksitas waktu
| Operasi | Rata-rata | Kasus terburuk |
|---|---|---|
| Put (sisipkan/perbarui) | O(1) | O(n) |
| Get (cari) | O(1) | O(n) |
| Hapus | O(1) | O(n) |
| Ruang | O(n) | O(n) |
Hash map di bahasa populer
| Bahasa | Tipe |
|---|---|
| Python | dict |
| Java | HashMap |
| JavaScript | Map / objek |
| C++ | std::unordered_map |
| Go | map |
Contoh penerapan
Menyisipkan pasangan ("cat", 3), ("dog", 5), ("cat", 9), ("emu", 7) ke map dengan 8 bucket, memakai hash(key) % 8. Anggap hash("cat") % 8 = 2, hash("dog") % 8 = 5, hash("emu") % 8 = 2:
| Langkah | Struktur | Aksi |
|---|---|---|
Put ("cat", 3) | bucket 2: [("cat", 3)] | Hash ke bucket 2; rantainya kosong, jadi tambahkan pasangannya. |
Put ("dog", 5) | bucket 2: [("cat", 3)], bucket 5: [("dog", 5)] | Hash ke bucket 5; rantainya kosong, jadi tambahkan pasangannya. |
Put ("cat", 9) | bucket 2: [("cat", 9)], bucket 5: [("dog", 5)] | Hash ke bucket 2; key "cat" sudah ada di rantai, jadi perbarui nilainya menjadi 9. |
Put ("emu", 7) | bucket 2: [("cat", 9), ("emu", 7)], bucket 5: [("dog", 5)] | Hash ke bucket 2; bertabrakan dengan "cat", key tidak ditemukan, jadi tambahkan pasangannya. |
Get "emu" | bucket 2: [("cat", 9), ("emu", 7)] | Hash ke bucket 2; pindai rantainya, lewati "cat", cocokkan "emu", kembalikan 7. |
Kapan memakai hash map
| Pakai saat | Hindari saat |
|---|---|
Kamu butuh pencarian, penyisipan, dan penghapusan rata-rata O(1) berdasarkan key yang persis. | Kamu butuh key yang tetap terurut atau range query: pakai BST yang seimbang atau sorted map. |
| Key-nya bisa di-hash dan kesamaannya terdefinisi dengan jelas (string, int, tuple). | Key-nya mutable dan bisa berubah setelah disisipkan, sehingga merusak bucket-nya. |
| Kamu sedang menghitung, menghapus duplikat, membuat cache, atau mengindeks berdasarkan sebuah ID. | Kamu butuh jaminan kasus terburuk O(log n), bukan batas rata-rata teramortisasi. |
| Urutan iterasi tidak penting, atau map yang mempertahankan urutan penyisipan sudah cukup. | Memori sangat terbatas: bucket, ruang cadangan untuk load factor, dan pointer menambah beban. |
Kode Hash Map
Implementasi Hash Map yang rapi dan siap dijalankan dalam Python, JavaScript, Java, C++, C. Pilih bahasa, salin kodenya, atau buka langsung di Coddy Playground.
Kode Hash Map dalam Python
1# Python's built-in dict is a hash map: O(1) average2# insert, lookup, and delete.3inventory = {"apple": 3, "banana": 7}4
5# Insert and update6inventory["cherry"] = 57inventory["apple"] += 28
9# Lookup, with .get for a safe default on missing keys10print("apple: ", inventory["apple"])11print("mango: ", inventory.get("mango", 0))12
13# Membership test and delete14print("banana in stock:", "banana" in inventory)15del inventory["banana"]16print("banana in stock:", "banana" in inventory)17
18# Iterate over key-value pairs19for fruit, count in sorted(inventory.items()):20 print(f"{fruit}: {count}")21
22# Classic hash map use case: counting frequencies23words = "the quick brown fox jumps over the lazy dog the end".split()24freq = {}25for word in words:26 freq[word] = freq.get(word, 0) + 127
28print("Occurrences of the:", freq["the"])29print("Most common word: ", max(freq, key=freq.get))Kode Hash Map dalam JavaScript
1// The built-in Map is the idiomatic hash map in JavaScript:2// any key type, insertion-ordered iteration, O(1) average lookups.3const ages = new Map();4
5ages.set("Alice", 30);6ages.set("Bob", 25);7ages.set("Carol", 35);8ages.set("Bob", 26); // set on an existing key updates the value9
10console.log("Bob:", ages.get("Bob"));11console.log("Has Dave?", ages.has("Dave"));12console.log("Size:", ages.size);13
14ages.delete("Carol");15console.log("Size after delete:", ages.size);16
17for (const [name, age] of ages) {18 console.log(`${name} is ${age}`);19}20
21console.log("Keys:", [...ages.keys()].join(", "));Kode Hash Map dalam Java
1import java.util.HashMap;2import java.util.Map;3
4public class Main {5 public static void main(String[] args) {6 Map<String, Integer> ages = new HashMap<>();7 ages.put("Alice", 30);8 ages.put("Bob", 25);9 ages.put("Carol", 35);10
11 System.out.println("Bob -> " + ages.get("Bob"));12 System.out.println("contains Carol: " + ages.containsKey("Carol"));13 System.out.println("Dave or default: " + ages.getOrDefault("Dave", -1));14
15 // getOrDefault makes frequency counting a one-liner16 String[] words = {"apple", "banana", "apple", "cherry", "apple"};17 Map<String, Integer> counts = new HashMap<>();18 for (String w : words) {19 counts.put(w, counts.getOrDefault(w, 0) + 1);20 }21 System.out.println("apple count: " + counts.get("apple"));22
23 ages.remove("Bob");24 System.out.println("size after remove: " + ages.size());25
26 for (Map.Entry<String, Integer> entry : ages.entrySet()) {27 System.out.println(entry.getKey() + " is " + entry.getValue());28 }29 }30}Kode Hash Map dalam C++
1#include <algorithm>2#include <iostream>3#include <string>4#include <unordered_map>5#include <vector>6
7int main() {8 std::unordered_map<std::string, int> ages;9
10 // Insert and update11 ages["alice"] = 30; // operator[] inserts or overwrites12 ages.insert({"bob", 25}); // insert keeps an existing value13 ages.emplace("carol", 41);14 ages["alice"] = 31;15
16 // Lookup17 auto it = ages.find("bob");18 if (it != ages.end()) {19 std::cout << "bob is " << it->second << "\n";20 }21 std::cout << "has dave: " << ages.count("dave") << "\n";22
23 // Remove24 ages.erase("carol");25
26 // Iterate (sort keys first: unordered_map has no defined order)27 std::vector<std::string> keys;28 for (const auto& entry : ages) keys.push_back(entry.first);29 std::sort(keys.begin(), keys.end());30 for (const std::string& name : keys) {31 std::cout << name << " = " << ages[name] << "\n";32 }33 std::cout << "size: " << ages.size() << "\n";34 return 0;35}Kode Hash Map dalam C
1#include <stdbool.h>2#include <stdio.h>3#include <stdlib.h>4#include <string.h>5
6#define BUCKETS 167
8typedef struct Node {9 char key[24];10 int value;11 struct Node* next;12} Node;13
14// A small string -> int hash map with a reusable put/get/remove API15typedef struct {16 Node* buckets[BUCKETS];17 int size;18} HashMap;19
20unsigned int hashKey(const char* key) {21 unsigned int h = 5381;22 for (; *key; key++) h = h * 33 + (unsigned char)*key;23 return h % BUCKETS;24}25
26void mapPut(HashMap* map, const char* key, int value) {27 unsigned int i = hashKey(key);28 for (Node* n = map->buckets[i]; n != NULL; n = n->next) {29 if (strcmp(n->key, key) == 0) {30 n->value = value;31 return;32 }33 }34 Node* n = malloc(sizeof(Node));35 strcpy(n->key, key);36 n->value = value;37 n->next = map->buckets[i];38 map->buckets[i] = n;39 map->size++;40}41
42bool mapGet(const HashMap* map, const char* key, int* out) {43 for (Node* n = map->buckets[hashKey(key)]; n != NULL; n = n->next) {44 if (strcmp(n->key, key) == 0) {45 *out = n->value;46 return true;47 }48 }49 return false;50}51
52void mapRemove(HashMap* map, const char* key) {53 Node** link = &map->buckets[hashKey(key)];54 while (*link != NULL) {55 if (strcmp((*link)->key, key) == 0) {56 Node* old = *link;57 *link = old->next;58 free(old);59 map->size--;60 return;61 }62 link = &(*link)->next;63 }64}65
66int main(void) {67 HashMap map = {0};68 mapPut(&map, "alice", 30);69 mapPut(&map, "bob", 25);70 mapPut(&map, "carol", 41);71 mapPut(&map, "alice", 31); // updates the existing key72 int age;73 if (mapGet(&map, "bob", &age)) printf("bob is %d\n", age);74 printf("has dave: %s\n", mapGet(&map, "dave", &age) ? "yes" : "no");75 mapRemove(&map, "carol");76 printf("size: %d\n", map.size);77 return 0;78}FAQ Hash Map
Apa perbedaan hash map dan hash table?
Pada dasarnya keduanya adalah struktur yang sama: array berisi bucket yang dialamatkan lewat hash dari key. Dalam pemakaian sehari-hari, "hash table" sering merujuk ke himpunan key atau teknik umumnya, sedangkan "hash map" menekankan penyimpanan pasangan key-value. Beberapa bahasa juga membedakan keduanya dari sisi thread safety (misalnya Hashtable vs HashMap di Java), tetapi algoritma intinya sama.
Berapa kompleksitas waktu hash map?
O(1) secara rata-rata dengan fungsi hash yang bagus dan load factor yang rendah. Pada kasus patologis ketika semua key bertabrakan di satu bucket, semuanya merosot menjadi O(n), itulah sebabnya resize dan hashing yang bagus itu penting.Bagaimana hash map menangani dua key yang di-hash ke bucket yang sama?
Hash map menyelesaikan tabrakan itu. Visualisasi ini memakai separate chaining: setiap bucket menyimpan list kecil, dan pasangan baru yang key-nya di-hash ke sana ditambahkan ke list itu. Saat pencarian, map memindai rantai pendek itu untuk mencari key yang cocok. Teknik alternatifnya adalah open addressing, yang mencari slot lain di dalam array.
Hash map vs binary search tree: mana yang sebaiknya dipakai?
O(1). Pakai binary search tree yang seimbang (seperti TreeMap atau std::map) saat kamu butuh key yang terurut, range query, atau pencarian predecessor/successor, yang berbiaya O(log n). BST mengorbankan sedikit kecepatan demi jaminan urutan yang tidak bisa diberikan hash map.Apa itu load factor dan mengapa memicu resize?
0.75. Resize bernilai O(n) tetapi jarang terjadi, jadi biayanya teramortisasi dan operasi rata-rata tetap O(1).Bisakah objek mutable seperti list dipakai sebagai key hash map?
TypeError: unhashable type untuk list. Jika kamu mengubah key setelah menyisipkannya, hash-nya berubah dan map tidak bisa lagi menemukannya di bucket yang benar, sehingga entri itu hilang tanpa peringatan. Pakai key yang immutable seperti string, angka, atau tuple.