我观察到HashMap
具有不同的元素顺序,即使在下一个程序开始时具有相同的数据。看起来HashMap
使用一些绝对地址来排序元素。是否有任何其他HashMap
实现,如果插入相同的数据,则具有相同的行为?
答案 0 :(得分:7)
我观察到
HashMap
具有不同的元素顺序,即使在下一个程序开始时具有相同的数据。
您不必观察任何事情,这是documented by HashMap
:
默认情况下,
HashMap
使用选定的哈希算法来提供对HashDoS攻击的抵抗。该算法是随机播种的,并且合理的尽最大努力从主机提供的高质量,安全的随机源生成该种子,而不会阻止该程序。
值得注意的是,这意味着在相同程序运行中具有相同插入值集的两个HashMap
可能会有不同的顺序:
use std::collections::HashMap;
fn main() {
let a = (0..100).zip(100..200);
let hash_one: HashMap<_, _> = a.clone().collect();
let hash_two: HashMap<_, _> = a.clone().collect();
// prints "false", most of the time
println!("{}", hash_one.into_iter().eq(hash_two));
}
文档还告诉您如何解决问题:
可以使用
HashMap
,default
和with_hasher
方法在每{ - 1}}基础上替换散列算法。 crates.io上有许多替代算法,例如fnv crate。
自从我致力于twox-hash以来,我将以此为例展示:
with_capacity_and_hasher
话虽如此,依赖于use std::hash::BuildHasherDefault;
use std::collections::HashMap;
use twox_hash::XxHash;
let mut hash: HashMap<_, _, BuildHasherDefault<XxHash>> = Default::default();
hash.insert(42, "the answer");
assert_eq!(hash.get(&42), Some(&"the answer"));
的顺序听起来像个坏主意。也许您应该使用不同的数据结构,例如BTreeMap
。
在其他情况下,您实际上关心插入的顺序。为此,indexmap crate是合适的。
答案 1 :(得分:2)
我相信linked-hash-map是事实上的箱子。
答案 2 :(得分:1)
将HashMap::with_hasher()
与默认RandomState
以外的其他内容一起使用。
答案 3 :(得分:0)
内置的 BTreeMap 是一个很好的选择。
我在 assert_eq! 中遇到了类似的问题。 diff每次都是随机排序,给HashMap调试带来了困难,但BTreeMap有key排序,所以不存在这个问题。
(来源:https://users.rust-lang.org/t/sort-hashmap-data-by-keys/37095/2)