【问题标题】:How can I use a custom hash function in a HashSet or HashMap?如何在 HashSet 或 HashMap 中使用自定义哈希函数?
【发布时间】:2015-02-21 09:13:54
【问题描述】:

由于 SipHasher 对于我的用例来说太慢了,我正在尝试实现一个自定义哈希函数。我找到了an example,我用它作为基础来编译所有内容。

我当前的代码如下所示:

use std::collections::hash_state::{DefaultState};
use std::collections::{HashMap, HashSet};
use std::default::Default;
use std::hash::{Hash, Hasher, SipHasher};
use std::marker;

pub struct FnvHasher(u64);

impl Default for FnvHasher {
    fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
}

impl Hasher for FnvHasher {
    fn write(&mut self, bytes: &[u8]) {
        let FnvHasher(mut hash) = *self;
        for byte in bytes {
            hash = hash ^ (*byte as u64);
            hash = hash * 0x100000001b3;
        }
        *self = FnvHasher(hash);
    }
    fn finish(&self) -> u64 { self.0 }
}

fn main() {
    let mut set:HashSet<i64, DefaultState<FnvHasher>> = HashSet::with_hash_state(DefaultState::<FnvHasher>);
}

当我编译时,我收到以下错误消息:

$ rustc -V
rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)

$ rustc hash.rs
hash.rs:26:86: 26:111 error: mismatched types:
 expected `std::collections::hash::state::DefaultState<FnvHasher>`,
    found `fn(core::marker::PhantomData<FnvHasher>) -> std::collections::hash::state::DefaultState<FnvHasher> {std::collections::hash::state::DefaultState}`
(expected struct `std::collections::hash::state::DefaultState`,
    found fn item) [E0308]
hash.rs:26         let mut set:HashSet<i64, DefaultState<FnvHasher>> = HashSet::with_hash_state(DefaultState::<FnvHasher>);
                                                                                                ^~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

如何获取上述示例以在 HashSet/HashMap 中编译或使用自定义哈希函数?

【问题讨论】:

    标签: rust hashcode


    【解决方案1】:

    看看DefaultState的定义:

    pub struct DefaultState<H>(marker::PhantomData<H>);
    

    你把它当作以前那样对待它:

    pub struct DefaultState<H>;
    

    此更改是最近的;现在必须明确使用泛型参数。

    为此,您现在必须使用Default::default(),因为该字段是私有的,防止写入文字表达式。因此,DefaultState::&lt;FnvHasher&gt; 变为 Default::default()

    一旦您为此使用Default::default(),您不妨全力以赴,将HashSet::with_hash_state(Default::default()) 替换为Default::default()

    let mut set: HashSet<i64, DefaultState<FnvHasher>> = Default::default();
    

    【讨论】:

      【解决方案2】:

      Rust 1.7 稳定了自定义哈希器的使用。例如,您可以使用fnv crate 中的FnvHasher

      extern crate fnv;
      
      use std::collections::HashMap;
      use std::hash::BuildHasherDefault;
      use fnv::FnvHasher;
      
      type HashMapFnv<K, V> = HashMap<K, V, BuildHasherDefault<FnvHasher>>;
      
      fn main() {
          let mut map = HashMapFnv::default();
          map.insert(1, "Hello");
          map.insert(2, ", world!");
          println!("{:?}", map);
      }
      

      【讨论】:

        猜你喜欢
        • 2015-07-06
        • 2012-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多