收集到 HashMap 时是否可以检测冲突?

Is it possible to detect collisions when collecting into a HashMap?

我想在将 IntoIterator 收集到 HashMap 时检测日志中的冲突并发出警告。当前收集到 HashMap 中的 Rust 行为是用最新的值默默地覆盖较早的值。

fn main() {
    let a = vec![(0, 1), (0, 2)];
    let b: std::collections::HashMap<_, _> = a.into_iter().collect();
    println!("{}", b[&0]);
}

输出:

2

(Playground)

一个可能的解决方法是收集到 Vec 然后手动编写转换代码,但这会引入额外的分配开销和不可读的代码。不消耗原始集合并比较 len()s 噪音较小,但仍然占用 1 倍以上的内存(?)并且无法检测到碰撞发生的确切位置。

是否有更优雅的方式来处理 HashMap 碰撞?

根据发生碰撞时您想做什么,您可以使用 fold(或 try_fold)和 entry API 来实现您的自定义功能:

use std::collections::HashMap;

fn main() {
    let a = vec![(0, 1), (0, 3), (0, 2)];

    let b: std::collections::HashMap<_, _> = a.into_iter().fold(HashMap::new(), |mut map, (k,v)| {
        map.entry(k)
            .and_modify(|_| println!("Collision with {}, {}!", k, v))
            .or_insert(v);
        map
    });

    println!("{}", b[&0]);
}

(Playground)