Entry API 与默认值
以更简洁的方式更新值。
Entry API 与默认值 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。
为什么使用 Entry API?
您经常需要在键存在时更新值,或者在键不存在时插入默认值。
使用 get 加上 insert 来完成这件事比较繁琐。entry API 可以用一步操作简洁地完成。
entry 返回一个位置
调用 entry(key) 会为您提供一个指向该键在映射中所在位置的句柄。
通过这个句柄,您可以决定如何处理:填入默认值,或者修改已有的值。
use std::collections::HashMap;
fn main() {
let mut m: HashMap<&str, i32> = HashMap::new();
m.entry("a").or_insert(0);
println!("{}", m["a"]);
}or_insert
or_insert(default) 只会在键缺失时插入默认值,然后返回该值的可变引用。
如果键已经存在,默认值会被忽略,您会得到已有的值。
use std::collections::HashMap;
fn main() {
let mut m = HashMap::new();
m.insert("a", 10);
m.entry("a").or_insert(99);
m.entry("b").or_insert(99);
println!("a={}, b={}", m["a"], m["b"]);
}通过引用修改值
由于 or_insert 会返回可变引用,因此您可以立即修改该值。
使用 * 取消引用即可直接在原位置更新。这正是计数操作的核心。
use std::collections::HashMap;
fn main() {
let mut m = HashMap::new();
let count = m.entry("hits").or_insert(0);
*count += 1;
*count += 1;
println!("hits = {}", m["hits"]);
}在循环中计数
经典模式是:对每个项目获取其位置,将默认值设为零,然后递增。
这样,每个项目只需一行逻辑即可统计出现次数。
use std::collections::HashMap;
fn main() {
let mut counts = HashMap::new();
for c in "hello".chars() {
*counts.entry(c).or_insert(0) += 1;
}
println!("l appears {} times", counts[&'l']);
}or_insert_with
当默认值的构造成本较高时,请使用 or_insert_with。它接收一个仅在键缺失时才运行的闭包。
这样可以避免构造可能永远用不到的值。
use std::collections::HashMap;
fn main() {
let mut m: HashMap<&str, Vec<i32>> = HashMap::new();
m.entry("nums").or_insert_with(Vec::new).push(1);
m.entry("nums").or_insert_with(Vec::new).push(2);
println!("{:?}", m["nums"]);
}and_modify
and_modify 仅在键已经存在时,对该值运行闭包。
将它与 or_insert 链接起来,即可同时处理两种情况:键存在时修改,否则插入初始值。
use std::collections::HashMap;
fn main() {
let mut m = HashMap::new();
m.insert("x", 5);
m.entry("x").and_modify(|v| *v += 10).or_insert(0);
m.entry("y").and_modify(|v| *v += 10).or_insert(1);
println!("x={}, y={}", m["x"], m["y"]);
}or_default
如果值的类型实现了 Default(例如整数的 0 或空的 Vec),or_default 就会使用它。
它是 or_insert(Default::default()) 的简写形式。
use std::collections::HashMap;
fn main() {
let mut m: HashMap<&str, i32> = HashMap::new();
*m.entry("score").or_default() += 7;
println!("score = {}", m["score"]);
}为每个键构建列表
按键将项目分组到向量中时,entry API 尤其有用。
对于每个键,第一次出现时将默认值设为空的 Vec,然后向已有的向量中执行 push。
use std::collections::HashMap;
fn main() {
let mut groups: HashMap<bool, Vec<i32>> = HashMap::new();
for n in [1, 2, 3, 4] {
groups.entry(n % 2 == 0).or_default().push(n);
}
println!("evens: {:?}", groups[&true]);
}为什么不用 get + insert?
先单独调用 get,再调用 insert,会查找键两次,还会与借用检查器发生冲突。
entry API 只查找一次,并为您提供一个恰好符合需求的安全引用,因此更快也更简洁。
综合运用
这里将计数与默认值结合起来,找出每个字母开头的不同单词数量。
请注意观察这一行计数模式的实际应用。
use std::collections::HashMap;
fn main() {
let words = ["ant", "art", "bee"];
let mut by_first: HashMap<char, i32> = HashMap::new();
for w in words {
*by_first.entry(w.chars().next().unwrap()).or_insert(0) += 1;
}
println!("a: {}", by_first[&'a']);
}快速检查
您希望每个 char 只查找一次就完成计数。
回顾
entry API 允许您通过一次查找完成插入或更新。
您使用了 or_insert、or_insert_with、or_default 和 and_modify,以简洁地统计项目并按键构建列表。
常见问题解答
「Entry API 与默认值」课时是免费的吗?
是的 — 「Entry API 与默认值」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。
「Entry API 与默认值」这节课中我会学到什么?
以更简洁的方式更新值。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Learn Rust Coding 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「Entry API 与默认值」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Learn Rust Coding 课中编写并运行代码吗?
能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 构建 HashMap
- Entry API 与默认值
- 使用 HashSet
- 计数和分组