替代/自定义键类型

Beginner

This tutorial is from open-source community. Access the source code

简介

在本实验中,我们将探索在 Rust 的 HashMap 中使用替代/自定义键类型,这些类型可以包括实现 EqHash 特性的类型,如 boolintuintString&str。此外,我们可以通过使用 #[derive(PartialEq, Eq, Hash)] 属性为自定义类型实现这些特性,从而允许它们在 HashMap 中用作键。

注意:如果实验未指定文件名,你可以使用任何你想要的文件名。例如,你可以使用 main.rs,并通过 rustc main.rs &&./main 进行编译和运行。

替代/自定义键类型

任何实现了 EqHash 特性的类型都可以作为 HashMap 中的键。这包括:

  • bool(不过不是很有用,因为只有两个可能的键)
  • intuint 及其所有变体
  • String&str(提示:你可以有一个以 String 为键的 HashMap,并使用 &str 调用 .get()

注意,f32f64 没有 实现 Hash,可能是因为浮点精度误差会使将它们用作哈希表键极易出错。

如果所有集合类中包含的类型也分别实现了 EqHash,那么这些集合类也会实现 EqHash。例如,如果 T 实现了 Hash,那么 Vec<T> 也会实现 Hash

你可以通过一行代码轻松地为自定义类型实现 EqHash#[derive(PartialEq, Eq, Hash)]

其余的工作编译器会完成。如果你想对细节有更多控制,可以自己实现 Eq 和/或 Hash。本指南不会涵盖实现 Hash 的具体细节。

为了尝试在 HashMap 中使用 struct,我们来创建一个非常简单的用户登录系统:

use std::collections::HashMap;

// Eq 要求你在类型上派生 PartialEq。
#[derive(PartialEq, Eq, Hash)]
struct Account<'a>{
    username: &'a str,
    password: &'a str,
}

struct AccountInfo<'a>{
    name: &'a str,
    email: &'a str,
}

type Accounts<'a> = HashMap<Account<'a>, AccountInfo<'a>>;

fn try_logon<'a>(accounts: &Accounts<'a>,
        username: &'a str, password: &'a str){
    println!("Username: {}", username);
    println!("Password: {}", password);
    println!("Attempting logon...");

    let logon = Account {
        username,
        password,
    };

    match accounts.get(&logon) {
        Some(account_info) => {
            println!("Successful logon!");
            println!("Name: {}", account_info.name);
            println!("Email: {}", account_info.email);
        },
        _ => println!("Login failed!"),
    }
}

fn main(){
    let mut accounts: Accounts = HashMap::new();

    let account = Account {
        username: "j.everyman",
        password: "password123",
    };

    let account_info = AccountInfo {
        name: "John Everyman",
        email: "j.everyman@email.com",
    };

    accounts.insert(account, account_info);

    try_logon(&accounts, "j.everyman", "psasword123");

    try_logon(&accounts, "j.everyman", "password123");
}

总结

恭喜你!你已经完成了“替代/自定义键类型”实验。你可以在 LabEx 中练习更多实验来提升你的技能。