HashMap 的遍历顺序为什么每次不同?容量是怎么长的?删光了内存还在吗?这篇用多次运行、分配器计数和自定义 Hasher 把默认哈希的随机种子、扩容序列、容量回收和哈希退化都真实跑了一遍。
编译:成功
运行(退出码 0):
map0 遍历顺序: bhadfgce
map1 遍历顺序: dgbhecaf
map2 遍历顺序: agecfhbd
同一个程序再运行 4 次,每次第一个 map 的顺序: ['aefgdhbc', 'hbfgcade', 'fbegdcah', 'ghbacfed'] 编译:成功
运行(退出码 0):
固定种子 map0 顺序: eadgfbhc
固定种子 map1 顺序: eadgfbhc
同一个 RandomState 对 "hello" 哈希两次: 6115208009943795217 6115208009943795217
另一个 RandomState: 6018114963070630449
DefaultHasher::new() 两次: 16156531084128653017 16156531084128653017 编译:成功
运行(退出码 0):
插入到第 0 个元素时 capacity = 0 累计 alloc 0 dealloc 0
插入到第 1 个元素时 capacity = 3 累计 alloc 1 dealloc 0
插入到第 4 个元素时 capacity = 7 累计 alloc 2 dealloc 1
插入到第 8 个元素时 capacity = 14 累计 alloc 3 dealloc 2
插入到第 15 个元素时 capacity = 28 累计 alloc 4 dealloc 3
插入到第 29 个元素时 capacity = 56 累计 alloc 5 dealloc 4
插入到第 57 个元素时 capacity = 112 累计 alloc 6 dealloc 5
插入到第 113 个元素时 capacity = 224 累计 alloc 7 dealloc 6
插入到第 225 个元素时 capacity = 448 累计 alloc 8 dealloc 7
插入到第 449 个元素时 capacity = 896 累计 alloc 9 dealloc 8
插入到第 897 个元素时 capacity = 1792 累计 alloc 10 dealloc 9
size_of::<HashMap<u64,u64>>() = 48Vec 的 2 倍扩容见Vec 扩容机制;HashMap 的 capacity 序列(3、7、14、28、……)是实测值,没有去读内部的桶数。
编译:成功
运行(退出码 0):
with_capacity(100): cap 112 (alloc 1 次)
插入 100 个后 cap 112(新增 alloc 0 次,没有再扩容)
第 101 个后 cap 112(新增 alloc 0 次)
另一个 map 插 100 个再删 90 个:len 10 cap() 54(删除期间 alloc 0 dealloc 0,内存没有释放)
shrink_to_fit 后 cap() 14(alloc 1 dealloc 1:换了块更小的内存)
clear() 之后 len 0 cap() 14(dealloc 0 次) 源码:
1 | use std::collections::HashMap;
2 | fn main() { let mut m: HashMap<f64, i32> = HashMap::new(); m.insert(1.0, 1); }
编译:失败
error[E0599]: the method `insert` exists for struct `HashMap<f64, i32>`, but its trait bounds were not satisfied
--> <实验目录>/src/u59e.rs:2:62
|
2 | fn main() { let mut m: HashMap<f64, i32> = HashMap::new(); m.insert(1.0, 1); }
| ^^^^^^
|
= note: the following trait bounds were not satisfied:
`f64: Eq`
`f64: Hash`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0599`.
编译:成功
运行(退出码 0):
n= 1000: 默认哈希 0.045 ms 恒等于 0 的哈希 0.493 ms
n= 2000: 默认哈希 0.061 ms 恒等于 0 的哈希 1.890 ms
n= 4000: 默认哈希 0.103 ms 恒等于 0 的哈希 7.521 ms
n= 8000: 默认哈希 0.215 ms 恒等于 0 的哈希 29.903 msBTreeMap 不依赖哈希,见BTreeMap 与 HashMap 对比。