在两个不同类实例中将相同项插入HashSet

huangapple go评论65阅读模式
英文:

Inserting same item into HashSets in two different class instances

问题

impl Birdwatcher {
    fn see(&mut self, bird: Bird) {
        // Additional logic goes here
        self.birds_seen.insert(bird);
    }
}
英文:

In the code below, I define a type Bird, and then a type Birdwatcher which has a HashSet of birds_seen.

Birdwatchers have a method .see(bird) which inserts a bird to their HashSet. (In context, this method has some other logic, so we cannot just call the hashset's .insert() method directly.)

In the main() function, I instantiate a bird as well as two birdwatchers. The code does not compile if I try to have both birdwatchers .see() the same bird:

use std::collections::HashSet;

fn main() {
    let falcon = Bird { name: "falcon".to_string(), speed: 25 };

    let mut alice = Birdwatcher { name: "Alice".to_string(), birds_seen: HashSet::new() };
    let mut bobby = Birdwatcher { name: "Bobby".to_string(), birds_seen: HashSet::new() };

    alice.see(falcon);
    // use of moved value: `falcon`
    // bobby.see(falcon);
}

#[derive(Hash, Eq, PartialEq)]
struct Bird {
    name: String,
    speed: isize,
}

struct Birdwatcher {
    name: String,
    birds_seen: HashSet<Bird>,
}

impl Birdwatcher {
    fn see(&mut self, bird: Bird) {
        // Additional logic goes here
        self.birds_seen.insert(bird);
    }
}

I though I could fix this by changing the .see() method to borrow the bird, as below, but this does not compile due to mismatched types:

impl Birdwatcher {
    fn see(&mut self, bird: &Bird) {
        // mismatched types: expected `Bird`, found `&Bird`
        self.birds_seen.insert(bird);
    }
}

How can I write the .see() method to allow the same bird to be seen by multiple birdwatchers?

答案1

得分: 2

我们不需要"使用"鸟来将它们存储在哈希集中;我们只需计算它们的哈希值(一次)并将其添加到集合中。

HashSet不是一个"哈希值的集合";它是一个使用哈希值的集合。它仍然包含并拥有被插入的值,就像Rust中的Vec或任何其他常规集合类型一样。

这是必要的,因为哈希值可能会发生碰撞 - 它们没有足够的位来实际保证不会发生碰撞 - 在这种情况下,集合将不得不回退到使用Eq来比较值本身。此外,HashSet允许对项进行迭代或删除,因此它必须拥有这些项才能生成它们。

如果您想要一个仅存储哈希值的集合,您需要创建一个存储这些哈希值的集合,而不是存储被哈希的值本身。

英文:

> we shouldn't need to "use" the birds to store them in a hashset; we can just compute their hash (once) and add it to the set.

A HashSet is not a set of hashes; it is a set which uses hashes. It still contains, owns, the values that are inserted just like a Vec or any other regular collection type in Rust would.

This is necessary because the hashes may collide — they don't have enough bits to practically guarantee not colliding — in which case the set will have to fall back to comparing the values themselves with Eq. Additionally, HashSet allows iteration over the items, or removal of the items, so it must own them to be able to produce them.

If you want a set that stores only hashes, you will need to make a set of those hashes, not of the values that are hashed to produced them.

huangapple
  • 本文由 发表于 2023年5月28日 09:09:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76349594.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定