To make something the key of a HashMap
, you need to satisfy 3 traits:
Hash
— How do you calculate a hash value for the type?
PartialEq
— How do you decide if two instances of a type are the same?
Eq
— Can you guarantee that the equality is reflexive, symmetric, and transitive? This requires PartialEq
.
This is based on the definition of HashMap
:
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
pub fn new() -> HashMap<K, V, RandomState> { /* ... */ }
}
Checking out the docs for HashSet
, you can see what traits it implements (listed at the bottom of the page).
There isn't an implementation of Hash
for HashSet
, so it cannot be used as a key in a HashMap
. That being said, if you have a rational way of computing the hash of a HashSet
, then you could create a "newtype" around the HashSet
and implement these three traits on it.
Here's an example for the "newtype":
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();
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…