是否可以使用HashSet作为HashMap的关键?

时间:2015-01-07 20:55:56

标签: hashmap rust

我想使用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`

1 个答案:

答案 0 :(得分:5)

要使某事成为HashMap的关键,您需要满足3个特征:

  1. Hash - 如何计算类型的哈希值?
  2. PartialEq - 您如何确定某个类型的两个实例是否相同?
  3. Eq - 你能保证平等是反身的,对称的和传递的吗?这需要PartialEq
  4. 这是基于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();
    }