如果我使用 hash()
或 hasher.write()
函数,像 1234
这样的数字会得到相同的结果,但是一个字节slice like 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
最佳答案
The default
Hasher
used byRandomState
. The internal algorithm is not specified, and so it and its hashes should not be relied upon over releases.
如果我们遵循RandomState
...
A particular instance
RandomState
will create the same instances ofHasher
, but the hashers created by two differentRandomState
instances are unlikely to produce the same result for the same values.
By default,
HashMap
uses a hashing algorithm selected to provide resistance against HashDoS attacks. The algorithm is randomly seeded, and a reasonable best-effort is made to generate this seed from a high quality, secure source of randomness provided by the host without blocking the program. Because of this, the randomness of the seed depends on the output quality of the system's random number generator when the seed is created. In particular, seeds generated when the system's entropy pool is abnormally low such as during system boot may be of a lower quality.
我稍微研究了一下,没有要求 hash()
和 write()
共享相同的行为。
唯一的要求是k1 == k2 -> hash(k1) == hash(k2)
对于 Hash
特征。 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()
具有您想要的行为,但并未说明情况总是如此(但我认为这是预期的行为并且不会改变,我问过 here )。
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());
}
关于hash - 为什么 hash() 和 hasher.write() 的结果不一样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54034727/