Han*_*lla 3 collections hashmap mutability rust
我为本书第 8.3 节中的第三个建议练习编写了一个可行的解决方案,但有些行为违背了我的直觉。具体来说,我似乎能够改变一个看起来被实例化为不可变的向量。
我已经包含了我认为相关的代码部分,省略了不Vec与HashMap.
我在代码块之后进行了一些猜测,但我确实可以对实际发生的情况进行更可靠的解释。
// Start by declaring a new HashMap. This is where the mystery begins for me.
let mut departments: HashMap<String, Vec<String>> = HashMap::new();
// This code deals with getting user input from stdin and has been elided
// ...
// Match the first string slice
match args[0] {
// Add an employee to a department in the HashMap
"add" => {
// POINT OF INTEREST 1
// Adding a department that isn't already in the HashMap will cause a new empty
// vector to be inserted at the newly created key
let list = departments.entry(args[2].to_string()).or_insert(Vec::new());
// In any case, we insert the employee's name into the vector associated with
// whatever department we got from stdin
list.push(args[1].to_string());
}
// List employees
"who" => match args[1] {
// List all employees in every department, employees shown in alphabetical order
"all" => {
for (department, employees) in &mut departments {
// POINT OF INTEREST 2
// Why am I allowed to sort this vector? The artifact underlying the reference
// was never explicitly made mutable.
employees.sort();
for ee in employees {
println!("{}: {}", department, ee);
}
}
}
// List all employees in a given department, employees shown in alphabetical order
dept => {
let employees = departments.get_mut(dept);
match employees {
Some(entries) => {
// POINT OF INTEREST 3
// This one is seems the least mysterious to me, since I get the value
// of the HashMap at `dept` through `.get_mut()`.
println!("{}:", dept);
entries.sort();
for ee in entries {
println!("\t{}", ee);
}
}
_ => (),
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
假设 1:在 处POINT OF INTEREST 1,我的调用.or_insert() 返回对新向量的可变引用,这就是为什么后来调用.sort()HashMap 中的值的原因。
这似乎不是一个可能的答案!一开始,我声明departments自己的类型是HashMap<String, Vec<String>>,而不是 HashMap<String, &mut Vec<String>>。
假设 2:当我声明departments为可变时,它的键和值继承了该可变性。这似乎也不太可能,因为在我(非常有限的)经验中没有任何迹象表明这样的事情是 Rust 的一个特性。我还认为,如果这本书的前 8 章中明确说明了这一点,它会引起我的注意,但众所周知,我以前会略过重要的细节。
Run Code Online (Sandbox Code Playgroud)for (department, employees) in &mut departments {
该for循环利用了这个IntoIter实现:
impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S> {
type Item = (&'a K, &'a mut V);
}
Run Code Online (Sandbox Code Playgroud)
由于这种实现,当您迭代 a 时,&mut HashMap<K, V>您会返回 的元组(&K, &mut V)。请注意,借用的键是不可变的,而值是可变的。这允许您修改值,因为employees是 类型&mut Vec<String>。
为什么映射能够返回可变引用?映射同时拥有键和值,因此如果需要,它可以返回对其中任何一个的可变引用。这就是作为所有者的含义:如果您愿意,您可以让其他人可变地借用您的物品。
HashMap很高兴让您改变值,因为这不会影响数据结构。它不允许您修改键,因为这会更改它们的哈希值并使它们在哈希表中的存储位置无效。HashMap 可以回来&mut K。借用检查员不会阻止它。但事实并非如此,因为调用者可能会破坏哈希图。
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |