预计我的哈希映射键的类型为&str
,尤其是&'static str
,并且我收到了自己的Box<String>
。
如何针对我的哈希图搜索字符串?
use std::collections::HashMap;
fn main() {
let mut map: HashMap<&str, u32> = HashMap::new();
let static_string = "a";
map.insert(static_string, 5);
let owned_boxed_string = Box::new(String::from("a"));
map.get(owned_boxed_string); // mismatched type (ok)
map.get(*owned_boxed_string); // mismatched type (ok)
map.get(&*owned_boxed_string); // trait bound not satisfied (?)
}
答案 0 :(得分:2)
让我们看看HashMap::get()
的定义:
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where
K: Borrow<Q>,
Q: Hash + Eq,
在您的代码中,K
是&'static str
,并且从对Q
的每次调用中推导出get
。用简单的英语来说,get()
引用了类型Q
,使得&'static str
实现了Borrow<Q>
。
基本原理是通常您将存储类型为String
的键,等等,并且您将使用类型为&str
的值进行搜索。自然,String
实现了Borrow<str>
,因此您可以做到这一点。
在您的情况下,您的密钥不是String
而是&'static str
...查看Borrow
的文档并查看实现了哪种Borrow<Q>
由&'static str
。我只能看到这两个总体实现:
impl<'_, T: ?Sized> Borrow<T> for &'_ T
impl<T: ?Sized> Borrow<T> for T
第一个陈述指出,如果您的映射键是对某些类型&K
的引用,则可以调用get(k: &K)
。第二个则说,如果您的密钥是K
,则可以呼叫get(k: &K)
。
因此对于您的&'static str
的特殊情况,它们被实现为:
impl Borrow<str> for &'static str
impl Borrow<&'static str> for &'static str
由此可以推断出您的函数是get(k: &str)
或get(k: &&str)
。最简单的选择是第一个。
现在,您可能会认为最后一行(map.get(&*owned_boxed_string);
)应该有效,因为该值的类型为&str
,但实际上不是,它的类型为&String
。如果HashMap::get()
收到了&str
,则可以正常编译,但是如果使用Borrow<Q>
,则编译器会感到困惑,并且失败。
TL; DR; :添加类型强制转换或临时类型变量:
map.get(&*owned_boxed_string as &str); //ok
map.get(&owned_boxed_string as &str); //also ok
let s: &str = &*owned_boxed_string;
map.get(s);
let s: &str = &owned_boxed_string;
map.get(s);
尽管更简单的解决方案(感谢@harmic用于下面的评论)是使用String::as_str()
,它可以处理所需的所有deref并仅返回必要的&str
:
map.get(owned_boxed_string.as_str());