unisbadri.com » Python Java Golang Typescript Kotlin Ruby Rust Dart PHP
Map

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() membuat HashMap kosong.
  • insert(k, v) menambahkan pasangan kunci-nilai ke dalam HashMap.

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, atau None 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 dalam HashMap.

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 nilai v jika kunci k belum ada dalam HashMap.

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 kunci k dari HashMap.

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 dan field_value tidak bisa digunakan lagi karena kepemilikannya sudah berpindah ke HashMap.

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 mengimplementasikan Hash, PartialEq, dan Eq untuk digunakan sebagai kunci dalam HashMap.

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.

« List
Date & Time »