我想使用HashSet
作为HashMap
的关键字。这可能吗?
use std::collections::{HashMap, HashSet};
fn main() {
let hmap: HashMap<HashSet<usize>, String> = HashMap::new();
}
给出以下错误:
error[E0277]: the trait bound `std::collections::HashSet<usize>: std::hash::Hash` is not satisfied
--> src/main.rs:4:49
|
4 | let hmap: HashMap<HashSet<usize>, String> = HashMap::new();
| ^^^^^^^^^^^^ the trait `std::hash::Hash` is not implemented for `std::collections::HashSet<usize>`
|
= note: required by `<std::collections::HashMap<K, V>>::new`
答案 0 :(得分:5)
要使某事成为HashMap
的关键,您需要满足3个特征:
Hash
- 如何计算类型的哈希值?PartialEq
- 您如何确定某个类型的两个实例是否相同?Eq
- 你能保证平等是反身的,对称的和传递的吗?这需要PartialEq
。这是基于HashMap
:
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
pub fn new() -> HashMap<K, V, RandomState> { /* ... */ }
}
检查HashSet
的文档,您可以看到它实现的特征(在页面底部列出)。
Hash
没有HashSet
的实现,因此它不能用作HashMap
中的密钥。话虽这么说,如果你有一个合理的方法来计算HashSet
的哈希值,那么你可以创建一个&#34; newtype&#34;围绕HashSet
并在其上实现这三个特征。
以下是&#34; newtype&#34;的示例:
use std::{
collections::{HashMap, HashSet},
hash::{Hash, Hasher},
};
struct Wrapper<T>(HashSet<T>);
impl<T> PartialEq for Wrapper<T>
where
T: Eq + Hash,
{
fn eq(&self, other: &Wrapper<T>) -> bool {
self.0 == other.0
}
}
impl<T> Eq for Wrapper<T> where T: Eq + Hash {}
impl<T> Hash for Wrapper<T> {
fn hash<H>(&self, _state: &mut H)
where
H: Hasher,
{
// do something smart here!!!
}
}
fn main() {
let hmap: HashMap<Wrapper<u32>, String> = HashMap::new();
}