本文简要介绍rust语言中 Struct std::collections::hash_map::HashMap
的用法。
用法
pub struct HashMap<K, V, S = RandomState> { /* fields omitted */ }
通过二次探测和 SIMD 查找实现的hash map。
默认情况下,HashMap
使用选定的哈希算法来抵御 HashDoS 攻击。该算法是随机播种的,并且会尽合理的最大努力从主机提供的高质量、安全的随机源生成此种子,而不会阻塞程序。因此,种子的随机性取决于系统随机数生成器在创建种子时的输出质量。特别是,当系统的熵池异常低时(例如在系统引导期间)生成的种子的质量可能较低。
目前默认的哈希算法是 SipHash 1-3,尽管将来可能会随时更改。虽然它的性能对于中等大小的 key 非常有竞争力,但对于整数等小 key 以及长字符串等大 key ,其他哈希算法的性能将优于它,尽管这些算法通常无法防御 HashDoS 等攻击。
可以使用 default
、 with_hasher
和 with_capacity_and_hasher
方法在每个 HashMap
的基础上替换哈希算法。有很多替代方案 hashing algorithms available on crates.io 。
要求键实现 Eq
和 Hash
特征,尽管这通常可以通过使用 #[derive(PartialEq, Eq, Hash)]
来实现。如果您自己实现这些,重要的是要满足以下属性:
k1 == k2 -> hash(k1) == hash(k2)
换句话说,如果两个键相等,则它们的哈希值必须相等。
以这样一种方式修改键是一个逻辑错误,即键的哈希(由 Hash
特征确定)或其相等性(由 Eq
特征确定)在映射中发生更改。这通常只能通过 Cell
、 RefCell
、全局状态、I/O 或不安全代码实现。未指定由此类逻辑错误导致的行为,但不会导致未定义的行为。这可能包括Panics、不正确的结果、中止、内存泄漏和不终止。
哈希表实现是 Google SwissTable 的 Rust 端口。 SwissTable 的原始 C++ 版本可以在 这里 中找到,并且 CppCon talk 概述了该算法的工作原理。
例子
use std::collections::HashMap;
// Type inference lets us omit an explicit type signature (which
// would be `HashMap<String, String>` in this example).
let mut book_reviews = HashMap::new();
// Review some books.
book_reviews.insert(
"Adventures of Huckleberry Finn".to_string(),
"My favorite book.".to_string(),
);
book_reviews.insert(
"Grimms' Fairy Tales".to_string(),
"Masterpiece.".to_string(),
);
book_reviews.insert(
"Pride and Prejudice".to_string(),
"Very enjoyable.".to_string(),
);
book_reviews.insert(
"The Adventures of Sherlock Holmes".to_string(),
"Eye lyked it alot.".to_string(),
);
// Check for a specific one.
// When collections store owned values (String), they can still be
// queried using references (&str).
if !book_reviews.contains_key("Les Misérables") {
println!("We've got {} reviews, but Les Misérables ain't one.",
book_reviews.len());
}
// oops, this review has a lot of spelling mistakes, let's delete it.
book_reviews.remove("The Adventures of Sherlock Holmes");
// Look up the values associated with some keys.
let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
for &book in &to_find {
match book_reviews.get(book) {
Some(review) => println!("{}: {}", book, review),
None => println!("{} is unreviewed.", book)
}
}
// Look up the value for a key (will panic if the key is not found).
println!("Review for Jane: {}", book_reviews["Pride and Prejudice"]);
// Iterate over everything.
for (book, review) in &book_reviews {
println!("{}: \"{}\"", book, review);
}
可以从数组初始化具有已知项目列表的HashMap
:
use std::collections::HashMap;
let solar_distance = HashMap::from([
("Mercury", 0.4),
("Venus", 0.7),
("Earth", 1.0),
("Mars", 1.5),
]);
HashMap
实现了 Entry API
,它允许使用复杂的方法来获取、设置、更新和删除键及其值:
use std::collections::HashMap;
// type inference lets us omit an explicit type signature (which
// would be `HashMap<&str, u8>` in this example).
let mut player_stats = HashMap::new();
fn random_stat_buff() -> u8 {
// could actually return some random value here - let's just return
// some fixed value for now
42
}
// insert a key only if it doesn't already exist
player_stats.entry("health").or_insert(100);
// insert a key using a function that provides a new value only if it
// doesn't already exist
player_stats.entry("defence").or_insert_with(random_stat_buff);
// update a key, guarding against the key possibly not being set
let stat = player_stats.entry("attack").or_insert(100);
*stat += random_stat_buff();
将 HashMap
与自定义键类型一起使用的最简单方法是派生 Eq
和 Hash
。我们还必须派生 PartialEq
。
use std::collections::HashMap;
#[derive(Hash, Eq, PartialEq, Debug)]
struct Viking {
name: String,
country: String,
}
impl Viking {
/// Creates a new Viking.
fn new(name: &str, country: &str) -> Viking {
Viking { name: name.to_string(), country: country.to_string() }
}
}
// Use a HashMap to store the vikings' health points.
let vikings = HashMap::from([
(Viking::new("Einar", "Norway"), 25),
(Viking::new("Olaf", "Denmark"), 24),
(Viking::new("Harald", "Iceland"), 12),
]);
// Use derived implementation to print the status of the vikings.
for (viking, health) in &vikings {
println!("{:?} has {} hp", viking, health);
}
相关用法
- Rust HashMap.get用法及代码示例
- Rust HashMap.try_insert用法及代码示例
- Rust HashMap.keys用法及代码示例
- Rust HashMap.iter用法及代码示例
- Rust HashMap.iter_mut用法及代码示例
- Rust HashMap.retain用法及代码示例
- Rust HashMap.with_capacity_and_hasher用法及代码示例
- Rust HashMap.clear用法及代码示例
- Rust HashMap.reserve用法及代码示例
- Rust HashMap.with_hasher用法及代码示例
- Rust HashMap.into_keys用法及代码示例
- Rust HashMap.into_values用法及代码示例
- Rust HashMap.get_mut用法及代码示例
- Rust HashMap.is_empty用法及代码示例
- Rust HashMap.drain用法及代码示例
- Rust HashMap.drain_filter用法及代码示例
- Rust HashMap.len用法及代码示例
- Rust HashMap.remove用法及代码示例
- Rust HashMap.insert用法及代码示例
- Rust HashMap.entry用法及代码示例
- Rust HashMap.capacity用法及代码示例
- Rust HashMap.contains_key用法及代码示例
- Rust HashMap.values用法及代码示例
- Rust HashMap.values_mut用法及代码示例
- Rust HashMap.new用法及代码示例
注:本文由纯净天空筛选整理自rust-lang.org大神的英文原创作品 Struct std::collections::hash_map::HashMap。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。