0Pricing
Learn Rust Coding · 课时

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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 构建 HashMap
  2. Entry API 与默认值
  3. 使用 HashSet
  4. 计数和分组
← 返回 Learn Rust Coding