如果我使用1234
或hash()
函数,则像hasher.write()
这样的数字具有相同的结果,但是像b"Cool"
这样的字节片却没有。我认为应该是一样的。为什么不呢?
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::mem;
fn main() {
let mut hasher = DefaultHasher::new();
1234.hash(&mut hasher);
println!("Hash is {:x}", hasher.finish());
let mut hasher = DefaultHasher::new();
hasher.write(unsafe { &mem::transmute::<i32, [u8; 4]>(1234) });
println!("Hash is {:x}", hasher.finish());
let mut hasher = DefaultHasher::new();
b"Cool".hash(&mut hasher);
println!("Hash is {:x}", hasher.finish());
let mut hasher = DefaultHasher::new();
hasher.write(b"Cool");
println!("Hash is {:x}", hasher.finish());
}
Hash is 702c1e2053bd76
Hash is 702c1e2053bd76
Hash is 9bf15988582e5a3f
Hash is 7fe67a564a06876a
答案 0 :(得分:3)
Hasher
使用的默认RandomState
。内部算法未指定,因此它及其散列不应该依赖过度发布。
如果我们遵循RandomState
...
特定的实例
RandomState
将创建Hasher
的相同实例,但是由两个不同的RandomState
实例创建的散列对于相同的值不太可能产生相同的结果。>
默认情况下,
HashMap
使用选定的哈希算法来抵抗HashDoS攻击。该算法是随机种子的,并且做出了合理的努力,以从主机提供的高质量,安全的随机性源生成该种子,而不会阻塞程序。因此,种子的随机性取决于创建种子时系统的随机数生成器的输出质量。特别是,当系统的熵池异常低(例如在系统启动期间)时生成的种子可能质量较低。
我稍微研究了一下,不要求hash()
和write()
具有相同的行为。
唯一的要求是Hash
特性必须使用k1 == k2 -> hash(k1) == hash(k2)
。 Hasher
特性具有相同的属性,但没有要求k1 -> hash(k1) == hasher(k1)
。
这是有道理的,因为Hash
特性是由用户实现的,他们可以根据需要实现。例如,可能想将salt添加到哈希中。
这是一个最小的完整且不可验证的示例,根据实现的不同,它可能产生相同的输出或不同的输出:
use std::collections::hash_map::{DefaultHasher, RandomState};
use std::hash::{BuildHasher, Hasher, Hash};
fn main() {
let s = RandomState::new();
let mut hasher = s.build_hasher();
b"Cool".hash(&mut hasher);
println!("Hash is {:x}", hasher.finish());
let mut hasher = s.build_hasher();
hasher.write(b"Cool");
println!("Hash is {:x}", hasher.finish());
let s = DefaultHasher::new();
let mut hasher = s.clone();
b"Cool".hash(&mut hasher);
println!("Hash is {:x}", hasher.finish());
let mut hasher = s.clone();
hasher.write(b"Cool");
println!("Hash is {:x}", hasher.finish());
}
您可以see,对切片执行Hash
也会写出切片的长度:
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Hash> Hash for [T] {
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
Hash::hash_slice(self, state)
}
}
另外,看起来hash_slice()
拥有您想要的行为,但并没有说总是这样(但是我认为这是预期的行为,并且不会改变,我问{{3 }}。
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
fn main() {
let s = DefaultHasher::new();
let mut hasher = s.clone();
std::hash::Hash::hash_slice(b"Cool", &mut hasher);
println!("Hash is {:x}", hasher.finish());
let mut hasher = s.clone();
hasher.write(b"Cool");
println!("Hash is {:x}", hasher.finish());
}