我有一个 Foo
集合。
struct Foo {
k: String,
v: String,
}
我希望有一个HashMap
,它的键为&foo.k
,值为foo
。
显然,如果不通过引入Rc
或者克隆/复制k
来重新设计Foo
,这是不可能实现的。
fn t1() {
let foo = Foo { k: "k".to_string(), v: "v".to_string() };
let mut a: HashMap<&str, Foo> = HashMap::new();
a.insert(&foo.k, foo); // Error
}
似乎可以通过滥用HashSet
的get()
方法来解决问题(Playground):
use std::collections::{HashMap, HashSet};
use std::hash::{Hash, Hasher, BuildHasher};
use std::collections::hash_map::Entry::*;
struct Foo {
k: String,
v: String,
}
impl PartialEq for Foo {
fn eq(&self, other: &Self) -> bool { self.k == other.k }
}
impl Eq for Foo {}
impl Hash for Foo {
fn hash<H: Hasher>(&self, h: &mut H) { self.k.hash(h); }
}
impl ::std::borrow::Borrow<str> for Foo {
fn borrow(&self) -> &str {
self.k.as_str()
}
}
fn t2() {
let foo = Foo { k: "k".to_string(), v: "v".to_string() };
let mut a: HashSet<Foo> = HashSet::new();
a.insert(foo);
let bar = Foo { k: "k".to_string(), v: "v".to_string() };
let foo = a.get("k").unwrap();
println!("{}", foo.v);
}
这很烦琐。假如一个
Foo
有多个字段和不同的 Foo
集合来根据不同的字段进行键控?
HashMap
暴露了一个接口会不安全;get_mut
就是一个例子(如果可以调用此方法且值拥有它们的键,则可能会使地图无效)。 具有安全接口的解决方案将必须以某种方式防止这种情况发生。 - trent