Map #
Dalam Rust, map atau dictionary yang sering digunakan untuk menyimpan pasangan kunci-nilai diimplementasikan melalui tipe data HashMap<K, V>
. HashMap
menyimpan data dalam bentuk pasangan kunci (K
) dan nilai (V
), di mana setiap kunci unik berasosiasi dengan satu nilai. HashMap
sangat efisien untuk mencari, menambah, dan menghapus data berdasarkan kunci.
Membuat HashMap
#
Untuk menggunakan HashMap
, Anda perlu mengimpor dari modul std::collections
.
Contoh Membuat HashMap
:
use std::collections::HashMap;
fn main() {
// Membuat HashMap kosong
let mut scores = HashMap::new();
// Menambahkan pasangan kunci-nilai
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
println!("{:?}", scores);
}
Penjelasan:
HashMap::new()
membuatHashMap
kosong.insert(k, v)
menambahkan pasangan kunci-nilai ke dalamHashMap
.
Mengakses Nilai dalam HashMap
#
Anda dapat mengakses nilai yang terkait dengan kunci menggunakan metode get
. Metode ini mengembalikan Option<&V>
, karena kunci mungkin tidak ada dalam HashMap
.
Contoh Mengakses Nilai:
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let team_name = String::from("Blue");
match scores.get(&team_name) {
Some(score) => println!("Score for {}: {}", team_name, score),
None => println!("No score found for {}", team_name),
}
}
Penjelasan:
get(&k)
mengembalikan referensi ke nilai (&V
) jika kunci ada, atauNone
jika tidak.
Iterasi pada HashMap
#
Anda dapat melakukan iterasi melalui pasangan kunci-nilai dalam HashMap
menggunakan for
loop.
Contoh Iterasi:
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
for (key, value) in &scores {
println!("Team: {}, Score: {}", key, value);
}
}
Penjelasan:
for (key, value) in &scores
melakukan iterasi melalui referensi pasangan kunci-nilai dalamHashMap
.
Memperbarui Nilai dalam HashMap
#
Ada beberapa cara untuk memperbarui nilai dalam HashMap
:
Menimpa Nilai Lama dengan Nilai Baru #
Jika Anda ingin menimpa nilai lama yang terkait dengan kunci yang ada, Anda cukup menggunakan metode insert
.
Contoh Menimpa Nilai:
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Blue"), 25); // Menimpa nilai lama
println!("{:?}", scores);
}
Penjelasan:
insert
dengan kunci yang sama akan menimpa nilai sebelumnya yang terkait dengan kunci tersebut.
Memasukkan Nilai jika Kunci Belum Ada #
Rust menyediakan metode entry
dengan or_insert
untuk memeriksa apakah kunci sudah ada. Jika tidak, Rust akan memasukkan nilai baru.
Contoh or_insert
:
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.entry(String::from("Yellow")).or_insert(50);
scores.entry(String::from("Blue")).or_insert(50); // Tidak menimpa karena "Blue" sudah ada
println!("{:?}", scores);
}
Penjelasan:
entry(k).or_insert(v)
hanya akan memasukkan nilaiv
jika kuncik
belum ada dalamHashMap
.
Memperbarui Nilai Berdasarkan Nilai Sebelumnya #
Anda bisa menggunakan nilai yang ada dalam HashMap
untuk menghitung nilai baru.
Contoh Memperbarui Berdasarkan Nilai Sebelumnya:
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
let score = scores.entry(String::from("Blue")).or_insert(0);
*score += 10;
println!("{:?}", scores);
}
Penjelasan:
*score += 10
menambahkan 10 ke nilai yang ada pada kunci"Blue"
.
Menghapus Elemen dari HashMap
#
Untuk menghapus elemen dari HashMap
, Anda dapat menggunakan metode remove
.
Contoh Menghapus Elemen:
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
scores.remove(&String::from("Blue"));
println!("{:?}", scores);
}
Penjelasan:
remove(&k)
menghapus pasangan kunci-nilai yang terkait dengan kuncik
dariHashMap
.
HashMap
dan Ownership
#
Saat Anda memasukkan nilai ke dalam HashMap
, Rust akan memindahkan kepemilikan (ownership
) dari nilai tersebut ke HashMap
. Ini berarti Anda tidak bisa lagi menggunakan nilai tersebut secara langsung setelah memasukkannya ke dalam HashMap
.
Contoh Ownership:
use std::collections::HashMap;
fn main() {
let field_name = String::from("Favorite color");
let field_value = String::from("Blue");
let mut map = HashMap::new();
map.insert(field_name, field_value);
// field_name dan field_value tidak bisa lagi digunakan setelah ini karena ownership telah berpindah ke HashMap
// println!("{}", field_name); // Akan menyebabkan error
}
Penjelasan:
- Setelah
insert
,field_name
danfield_value
tidak bisa digunakan lagi karena kepemilikannya sudah berpindah keHashMap
.
Penanganan Nilai Duplikat dan Konflik Hash #
Rust menggunakan fungsi hash bawaan untuk menghitung nilai hash dari kunci yang dimasukkan ke dalam HashMap
. Jika dua kunci menghasilkan nilai hash yang sama (konflik hash), Rust akan mengelola hal ini secara internal dengan menyimpan kedua nilai di lokasi yang sama dan menggunakan pencarian linier untuk menemukan yang benar.
Namun, Anda dapat mengimplementasikan tipe kustom yang memiliki logika hashing sendiri dengan mengimplementasikan trait Hash
dan Eq
.
Contoh Tipe Kustom dengan Trait Hash
:
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
#[derive(Debug)]
struct CustomKey {
id: u32,
name: String,
}
impl Hash for CustomKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
self.name.hash(state);
}
}
impl PartialEq for CustomKey {
fn eq(&self, other: &Self) -> bool {
self.id == other.id && self.name == other.name
}
}
impl Eq for CustomKey {}
fn main() {
let mut map = HashMap::new();
let key = CustomKey {
id: 1,
name: String::from("Alice"),
};
map.insert(key, 100);
println!("{:?}", map);
}
Penjelasan:
CustomKey
adalah tipe kustom yang mengimplementasikanHash
,PartialEq
, danEq
untuk digunakan sebagai kunci dalamHashMap
.
Performa HashMap
#
Secara umum, operasi dasar pada HashMap
(penyisipan, penghapusan, dan pencarian) memiliki kompleksitas waktu rata-rata O(1). Namun, ini tergantung pada seberapa baik fungsi hash mendistribusikan kunci ke dalam bucket.
Untuk kasus-kasus di mana performa hashing default Rust tidak cukup baik, Anda bisa menggunakan crate hashbrown
atau mengimplementasikan fungsi hash kustom yang lebih cocok untuk kebutuhan spesifik Anda.
Kesimpulan #
HashMap<K, V>
di Rust adalah struktur data yang sangat berguna untuk menyimpan dan mengelola pasangan kunci-nilai. Dengan mendukung operasi seperti penyisipan, penghapusan, pencarian, dan iterasi, HashMap
memungkinkan Anda untuk mengelola data dengan cara yang efisien dan fleksibel. Selain itu, Rust menjamin keamanan tipe dan kepemilikan saat bekerja dengan HashMap
, yang membantu mencegah bug umum seperti kebocoran memori dan penggunaan memori yang tidak valid.
Memahami cara menggunakan HashMap
dengan benar akan membantu Anda menulis kode yang lebih efektif dan aman di Rust.