我想做以下事情:
Vec
如何有效地做到这一点?我自然认为我可以使用match:
match
use std::collections::HashMap; // This code doesn't compile. let mut map = HashMap::new(); let key = "foo"; let values: &Vec<isize> = match map.get(key) { Some(v) => v, None => { let default: Vec<isize> = Vec::new(); map.insert(key, default); &default } };
当我尝试时,它给了我这样的错误:
error[E0502]: cannot borrow `map` as mutable because it is also borrowed as immutable --> src/main.rs:11:13 | 7 | let values: &Vec<isize> = match map.get(key) { | --- immutable borrow occurs here ... 11 | map.insert(key, default); | ^^^ mutable borrow occurs here ... 15 | } | - immutable borrow ends here
我最终做了这样的事情,但我不喜欢它执行两次查找(map.contains_key和map.get):
map.contains_key
map.get
// This code does compile. let mut map = HashMap::new(); let key = "foo"; if !map.contains_key(key) { let default: Vec<isize> = Vec::new(); map.insert(key, default); } let values: &Vec<isize> = match map.get(key) { Some(v) => v, None => { panic!("impossiburu!"); } };
有没有一种安全的方法可以只用一个来做到这一点match?
您可以使用entry提供的 API来实现您的目标HashMap。该entry方法允许您在键不存在时插入一个值,并返回对该值的可变引用,或者如果键存在则返回对现有值的可变引用。这避免了多次查找的需要并确保安全的可变借用。
entry
HashMap
以下是使用 API 重写代码的方法entry:
锈复制代码use std::collections::HashMap; let mut map = HashMap::new(); let key = "foo"; let values: &Vec<isize> = match map.entry(key) { std::collections::hash_map::Entry::Occupied(entry) => entry.into_mut(), std::collections::hash_map::Entry::Vacant(entry) => entry.insert(Vec::new()), };
在此代码中:
map.entry(key)
entry.into_mut()
entry.insert(Vec::new())
这样,您只需执行一次查找即可安全高效地实现您的目标。