Create two different Hashers?

Hello,

Can I create two differently behaving Hasher instances using only std without deprecation? I see there is DefaultHasher, but the only way to create one seems to be via DefaultHasher::new(), and these seem to behave the same. There actually different Hasher implementations, but all I can find are deprecated.

I want to create keys for collections using hashing. If I use u64, collision probability is too high, but for (u64, u64) it's acceptable, as long as I can get two independent values.

Thanks!

Best, Oliver

You can create a custom hasher by implementing the Hasher trait.

Thanks, suppose I could implement my own. Is there a reason why the existing implementations are deprecated? Actually, even DefaultHasher is using the deprecated SipHasher13 under the hood.

I think this works for me:

use std::hash::{Hasher, Hash};
use std::collections::hash_map::DefaultHasher;

#[derive(Eq, PartialEq)]
pub(crate) struct HashKey {
    hash1: u64,
    hash2: u64,
}

const SALT: [u64; 8] = [126, 39, 22, 47, 75, 207, 77, 5];

impl From<&str> for HashKey {
    fn from(string: &str) -> Self {
        let mut hasher1 = DefaultHasher::new();
        string.hash(&mut hasher1);
        let hash1 = hasher1.finish();
        let mut hasher2 = DefaultHasher::new();
        SALT.hash(&mut hasher2);
        string.hash(&mut hasher2);
        let hash2 = hasher2.finish();
        HashKey { hash1, hash2 }
    }
}

You should use an external crate to get a new Hasher.

Here's a paragraph from the book that explains it, but basically Rust's standard library does not want to provide hashing algorithms. They want to provide ONE algorithm that is safe enough to always be good enough. That's what DefaultHasher is. It's not guaranteed to be the same algorithm that it was before, or as fast as it was before, it's just what the maintainers think is safe enough to be shipped out as the general-purpose Hasher.

https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#hashing-functions

2 Likes