2015-01-07 75 views
2

我想用HashSet作爲HashMap的關鍵。這可能嗎?是否可以使用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` 

回答

3

要東西HashMap的關鍵,需要滿足3個性狀:

  1. Hash - 如何計算哈希值對於類型?
  2. PartialEq - 如何確定某個類型的兩個實例是否相同?
  3. Eq - 你能保證平等是自反的,對稱的和傳遞性的嗎?這需要PartialEq

這是基於HashMap定義:

impl<K: Hash + Eq, V> HashMap<K, V, RandomState> { 
    pub fn new() -> HashMap<K, V, RandomState> { /* ... */ } 
} 

檢查出的文檔的HashSet,你可以看到它實現什麼特性(在頁面的底部列出)。

對於HashSet沒有Hash的實現,因此它不能用作HashMap中的密鑰。話雖如此,如果你有一個合理的方式來計算HashSet的散列,那麼你可以圍繞HashSet創建一個「新類型」,並在其上實現這三個特徵。

下面是一個例子,爲 「NEWTYPE」:

use std::collections::{HashMap, HashSet}; 
use std::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(); 
} 
+0

謝謝你的回答!它肯定我需要學習很多東西。 – jojoshua

相關問題