我只学习了几天 Rust。我认为这两个代码示例是相同的,但编译器不同意。你能解释一下第二部分发生了什么吗?为什么我需要取消引用key
两次,但value
一次?
第一部分
use std::collections::HashMap;
let mut h = HashMap::new();
h.insert(1, 1);
h.insert(2, 2);
let mut keys: Vec<i32> = Vec::new();
let mut values: Vec<i32> = Vec::new();
for (k, v) in &h {
keys.push(**k);
values.push(*v);
}
第二部分
fn main() {
let mut v = vec![2, 3, 5, 1, 2, 3, 8, 6, 3, 1, 4, 6, 7];
use std::collections::HashMap;
let mut h = HashMap::new();
for element in &v {
let count = h.entry(element).or_insert(0);
*count += 1;
}
let mut keys: Vec<i32> = Vec::new();
let mut values: Vec<i32> = Vec::new();
for (k, v) in &h {
keys.push(**k);
values.push(*v);
}
println!("{:?}", keys);
}
由于您没有指定HashMap
的类型,编译器对其进行了推断。
let v = vec![1i32, 2, 3];
let mut h = HashMap::new();
for i in &v {
h.insert(i, ());
}
这里的h
类型是HashMap<&i32, ()>
,i
的类型是&i32
。为什么i
有&i32
类型?因为这就是IntoIterator
&Vec
的实施方式。通常,当您循环访问引用时,您将获得引用。
如果您想要密钥类型不是引用的HashMap
,您可以这样说。然后,当您尝试插入引用时,您将收到不同的错误消息。
let v = vec![1i32, 2, 3];
let mut h: HashMap<i32, ()> = HashMap::new();
for i in &v {
h.insert(i, ());
}
error[E0308]: mismatched types
--> src/main.rs:6:18
|
6 | h.insert(i, ());
| ^ expected i32, found &i32
|
= note: expected type `i32`
found type `&i32`
然后你可以用*i
替换要插入的键。
HashMap
的完整类型推断为HashMap<&i32, i32>
。这可以通过使用以下技巧进行验证:
let () = h;
触发类型错误:
error[E0308]: mismatched types
--> src/main.rs:17:9
|
17 | let () = h;
| ^^ expected struct `std::collections::HashMap`, found ()
|
= note: expected type `std::collections::HashMap<&{integer}, {integer}>`
found type `()`
(此时编译器还不确定最终类型是否会HashMap<&i32, i32>
,因此类型签名中的{integer}
s(
当你迭代&h
时,(k, v)
元组的类型是(&&i32, &i32)
(也可以用前面提到的技巧来确认(,这就是为什么你需要对k
进行双重取消引用,而对v
只需要一个取消引用。
你只需要取消引用一次
下面是代码工作的示例