邢台市建设局官方网站,网站后台管理系统论文,删除wordpress 后台,邢台做网站推广费用8.6.0. 本章内容
第八章主要讲的是Rust中常见的集合。Rust中提供了很多集合类型的数据结构#xff0c;这些集合可以包含很多值。但是第八章所讲的集合与数组和元组有所不同。
第八章中的集合是存储在堆内存上而非栈内存上的#xff0c;这也意味着这些集合的数据大小无需在编…8.6.0. 本章内容
第八章主要讲的是Rust中常见的集合。Rust中提供了很多集合类型的数据结构这些集合可以包含很多值。但是第八章所讲的集合与数组和元组有所不同。
第八章中的集合是存储在堆内存上而非栈内存上的这也意味着这些集合的数据大小无需在编译时就确定在运行时它们可以动态地变大或变小。
本章主要会讲三种集合Vector、String和HashMap本文
喜欢的话别忘了点赞、收藏加关注哦对接下来的教程有兴趣的可以关注专栏。谢谢喵(ω)
8.6.1. 更新HashMap
HashMap的大小可变指的是其中的键值对数量可变但是在每个时刻一个键只能对应一个值当想要更新HashMap中的数据的时候可能有这么几种情况 想要更新的键在HashMap中已经存在一个对应的值 用新的值代替现有的值保留现有的值忽略新的值合并现有的值和新的值也就是说对现有的值进行修改 键不存在添加一对键和值
1. 替换覆盖现有的值
如果向HashMap插入一对键值对但键已经存在程序就会把新值赋给这个键原来的就被覆盖了。如下例
use std::collections::HashMap; fn main() { let mut scores HashMap::new(); scores.insert(String::from(dev1ce), 0); scores.insert(String::from(dev1ce), 60); println!({:?}, scores)
}这里为通一个键赋了两次值第一次是0第二次是60那么第一次的就会被第二次覆盖掉也就是说最终dev1ce对应的值是60。
输出
{dev1ce: 60}2. 只在键不存在任何值的情况下才插入值
这个情况是最常见的对于这种情况首先需要检查原HashMap中是否已经存在这个键如果不存在再插入新值。
Rust提供了entry这个方法来实现检查原HashMap中是否已经存在这个键的功能。它的参数为键它的返回值是一个枚举Entry代表值是否存在。看个例子
use std::collections::HashMap; fn main() { let mut scores HashMap::new(); scores.insert(String::from(dev1ce), 0); let e scores.entry(String::from(dev1ce)); println!({:?}, e);
}这是键已经存在的情况来看一下输出
Entry(OccupiedEntry { key: dev1ce, value: 0, .. })也就是说如果键已经存在那么entry这个方法会返回Entry枚举下的OccupiedEntry这个变体并且关联已经存在的键值对。
那来试一下键不存在的情况。代码如下
use std::collections::HashMap; fn main() { let mut scores HashMap::new(); scores.insert(String::from(dev1ce), 0); let e scores.entry(String::from(Zywoo)); println!({:?}, e);
}输出
Entry(VacantEntry(Zywoo))如果键不存在那么它会返回Entry枚举下的VacantEntry变体并且关联这个新的键。
现在有办法检查原HashMap中是否已经存在这个键那么如何根据是否存在实现插入或不插入值呢
Rust提供了or_insert方法其参数是想要添加的值它可以接收Entry枚举类型根据这个类型的两个变体来实现是否插入的功能。如果它接收到了OccupiedEntry(已经存在的情况)这个变体它就会不插入值反之如果接收到了VacantEntry(不存在的情况)变体它就不会执行插入操作。最重要的一点是它是有返回值的它的返回值是这个键对应值的可变引用存在就返回HashMap中原有的键所对应的值的可变引用不存在就先添加键值对然后返回值的可变引用根据这个特性可以实现一些简单的计数器后文会讲。
看下例子
use std::collections::HashMap; fn main() { let mut scores HashMap::new(); scores.insert(String::from(dev1ce), 0); scores.entry(String::from(Zywoo)).or_insert(100); scores.entry(String::from(dev1ce)).or_insert(60);println!({:?}, scores);
}第一个entry语句查找了Zywoo发现没有就返回VacantEntryor_insert接收到了就根据VacantEntry所关联的键和传入的参数100创建了(“Zywoo”, 100)这个键值对。第二个entry语句查找了dev1ce发现有了就返回OccupiedEntryor_insert接收到了就停止插入新值所以会保持(“dev1ce”, 0)不变。
输出:
{Zywoo: 100, dev1ce: 0}如果这么讲还有些复杂那么你可以把scores.entry(String::from(Zywoo)).or_insert(100);看作两行代码
let e scores.entry(String::from(Zywoo));
e.or_insert(100);3.基于现有的值来更新
先看例子
use std::collections::HashMap; fn main() { let text Thats one small step for [a] man, one giant leap for mankind.; let mut map HashMap::new(); for word in text.split_whitespace() { let count map.entry(word).or_insert(0); *count 1; } println!({:#?}, map);
}这个例子首先声明了一个字符串字面值一段话赋给了text。然后创建了map这个HashMap接着使用了for循环text.split_whitespace()就是把text分割为了一组字符串的遍历器用for来遍历。遍历的时候就判断单词在这个map里出现没出现了就不插入新值了没出现就插入0作为新的键值对。最重要的是理解count由于or_insert方法的返回值是这个键对应值的可变引用所以没出现一次就把值的可变引用先解引用在自加1就相当于完成了一次统计。
8.6.2. Hash函数
在默认情况下HashMap使用加密功能强大的Hash函数可以抵抗拒绝服务(DoS)攻击。但这种函数它不是可用的最快的Hash算法它的优势是具有较好的安全性。如果觉得它性能不好也可以指定不同的hasher来切换到另一个函数。hasher指的是实现BuildHasher trait的类型。