英文:
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
.
Birdwatcher
s 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论