1.HahsMap
https://rustwiki.org/zh-CN/std/collections/struct.HashMap.html
跟着文档,查看一下hashmap的方法,调试,输出一下,就能学会使用了。
use std::collections::HashMap;
use std::any::type_name;
//输出变量类型
fn print_type_of<T>(_: &T) {
println!("{}", type_name::<T>());
}
//最基本的创建hashmap
fn test1() {
// let mut m = HashMap::new(); //std::collections::hash::map::HashMap<i32, i32>
let mut m = HashMap::with_capacity(7); //因为后面有插值,才不用自定类型
// let mut m:HashMap<i32,i32> = HashMap::new(); //std::collections::hash::map::HashMap<i32, i32>
m.insert(0,1);
m.insert(2,3);
print_type_of(&m);
//为什么key和v都是i32的类型?
//这里m不使用引用,就会获取m的所有权,后面将不能再使用m
//不使用引用,k,v都是i32,m使用引用,k,v都是&i32
for (k,v) in &m {
println!("{} {}",k,v);
print_type_of(&v);
print_type_of(&k);
}
println!("{}",m.contains_key(&2));
}
//hashmap常规使用
fn test2() {
let range = 0..5;
// let mut m:HashMap<i32,i32> = range.map(|i|(i,i+1)).collect();
let mut m = HashMap::from([
(0,1),(1,2),(2,3),(3,4),(4,5)
]);
m.insert(5,7);
print_type_of(&m); //std::collections::hash::map::HashMap<i32, i32>
println!("len: {}",m.len());
println!("capacity: {}",m.capacity());
//输出是无序的
for (k,v) in &m {
println!("k: {},v: {}",k,v);
print_type_of(&k);
print_type_of(&v);
}
//查询是否包含指定key
println!("{}",m.contains_key(&7)); //false
println!("{}",m.contains_key(&5)); //true
//获取指定key的value
println!("{:?}",m.get(&7)); //None
println!("{:?}",m.get(&5)); //Some(7)
let mut five = m.get_mut(&5);
// let mut num = 999; //这样改是没有用的,必须在模式匹配中才有效
// five.replace(&mut num);
match five {
Some(ref mut v) => {
**v = 999;
print_type_of(&v); //&mut &mut i32
},
_ =>{},
}
println!("{}",m[&5]); //999
//移除指定key
println!("{:?}",m.remove(&7)); //None
println!("{:?}",m.remove(&5)); //Some(999)
print_type_of(&m.remove_entry(&3)); //core::option::Option<(i32, i32)>
println!("{:?}",m.remove_entry(&2));//Some((2, 3))
print_type_of(&m.get_key_value(&1)); //core::option::Option<(&i32, &i32)>
println!("{:?}",m.get_key_value(&1)); //Some((1, 2)),自动解引用了
//直接通过索引找key,找不存在的key就会panic
println!("{}",m[&5]); //no entry found for key,然后panic
}
fn get_five() ->i32 {
5
}
//map中entry的用法
fn test3() {
let range = 0..6;
// let mut m:HashMap<i32,i32> = range.map(|i|(i,i+2)).collect();
let mut m:HashMap<i32,i32> = (0..6).map(|i|(i,i+2)).collect();
// print_type_of(&m.entry(0));
println!("len {}",m.len());
//最好是不要创建变量来调用m.entry(),e的每次调用都会消耗掉所有权,从而需要重新调用m.entry()
/*let e = m.entry(10);
print_type_of(&e); //Enum std::collections::hash_map::Entry std::collections::hash::map::Entry<i32, i32>
e.or_insert(100); //不存在的key,就会创建并插入
// let e = m.entry(10);
println!("{}",e.or_insert(100));
// let e = m.entry(10);
*e.or_insert(100) = 66;
// let e = m.entry(10);
println!("{}",e.or_insert(100));
return;*/
//or_insert(v) 直接插入一个值
/*
m.entry(10).or_insert(100);
println!("len {}",m.len()); //长度增加了
println!("{:?}",m.entry(10));
*m.entry(10).or_insert(66) = 66;
println!("{:?}",m.entry(10));
*/
//or_insert_with(||v) 利用闭包来创建插入的值
/*
m.entry(10).or_insert_with(||100);
println!("len {}",m.len()); //长度增加了
println!("{:?}",m.entry(10));
*m.entry(10).or_insert_with(||100) = 66;
println!("{:?}",m.entry(10));
*/
/*fn Six()->i32 {
6
}
// let six = || 6;
// let six = ||->i32 {6};
m.entry(10).or_insert_with(Six);
// m.entry(10).or_insert_with(get_five); //闭包也行,函数也行
println!("len {}",m.len()); //长度增加了
println!("{:?}",m.entry(10));
*m.entry(10).or_insert_with(||100) = 66;
println!("{:?}",m.entry(10));
*/
// return;
//这样使用,就像最开始创建m时,根据k,生成v
m.entry(10).or_insert_with_key(|k|k+2);
println!("{:?}",m.entry(10));
println!("len {}",m.len()); //长度增加了
*m.entry(10).or_insert_with_key(|k|k+2) = 66;
println!("{:?}",m.entry(10));
m.entry(10).and_modify(|e| *e*=10); //and_modify,只能在entry存在时,进行修改
println!("{:?}",m.entry(10));
m.entry(100).and_modify(|e| *e*=10); //and_modify,entry不存在时
println!("{:?}",m.entry(100)); //Entry(VacantEntry(100))
m.entry(100).or_default();
println!("{:?}",m.entry(100)); //插入了i32的默认值,为0
*m.entry(100).or_default() = 166;
println!("{:?}",m.entry(100));
/*
//entry,使用后会消耗
let e = m.entry(100);
let v = e.or_default();
*v = 166;
println!("{:?}",m.entry(100));
let e = m.entry(100);
let v = e.or_insert(66);
*v = 188;
println!("{:?}",m.entry(100));
*/
}
fn test4() {
let mut m = HashMap::from([
("a",1),("b",2),("c",3)
]);
//m.keys(),返回键的引用
for k in m.keys() {
println!("{}",k);
print_type_of(&k); //&&str
}
/*
//into_keys(),将获取m的所有权
let keys:Vec<_> = m.into_keys().collect(); //会消耗m,m将失去所有权
print_type_of(&keys); //alloc::vec::Vec<&str>
println!("{:?}",keys); //["a", "b", "c"]
// print_type_of(&m); //不能再使用m
*/
//m.values_mut(),返回值的可变引用
for v in m.values_mut() {
*v *=10;
print_type_of(&v); //&mut i32
}
//m.values(),返回值的引用
for v in m.values() {
println!("{}",v);
print_type_of(&v); //&i32
}
/*
//into_values(),将获取m的所有权
let values:Vec<_> = m.into_values().collect();
print_type_of(&values); //alloc::vec::Vec<i32>
println!("{:?}",values);
// print_type_of(&m); //不能再使用m
*/
//不加&也会获取m的所有权
for (k,v) in &m {
println!("{} {}",k,v);
print_type_of(&k);
print_type_of(&v);
break;
}
print_type_of(&m); //遍历不加&就不能再使用m
//k和v都是引用,但是v可变
for (_,v) in m.iter_mut() {
*v +=16;
print_type_of(&v); //&mut i32
}
//使用m.iter(),效果和&m一致
for (k,v) in m.iter() {
println!("{} {}",k,v);
print_type_of(&k);
print_type_of(&v);
break;
}
print_type_of(&m);
println!("{:?}",m); //{"c": 46, "a": 26, "b": 36}
//k:&&str,v:&mut i32同迭代器,都是引用
//同模式匹配一直,这里可以是ref k ,k,&k ,k的类型分别是&&&str,&&str,&str
//原地操作,删除返回false的key-value
m.retain(|k,v|{
print_type_of(&k);
print_type_of(&v);
if v==&36 || *v == 36 {
*v = 999;
}
true
});
println!("{:?}",m); //{"c": 46, "a": 26, "b": 36}
let cm:Vec<_> = m.clone().into_iter().collect();
print_type_of(&cm); //alloc::vec::Vec<(&str, i32)>
println!("{:?}",cm); //[("a", 26), ("b", 999), ("c", 46)]
print_type_of(&m.clone().into_iter()); //std::collections::hash::map::IntoIter<&str, i32>
print_type_of(&m.iter()); //std::collections::hash::map::Iter<&str, i32>
print_type_of(&m.iter_mut()); //std::collections::hash::map::IterMut<&str, i32>
println!("{}",m.capacity());
m.clear(); //容量还在,但是数据清除了
println!("{}",m.capacity());
}
fn main() {
test4();
}
2.BTreemap
个人感觉使用起来和HashMap没有太大区别,除了没有capacity这个属性,所以也没有with_capacity()来新建
use std::collections::BTreeMap;
use std::any::type_name;
//输出变量类型
fn print_type_of<T>(_: &T) {
println!("{}", type_name::<T>());
}
//最基本的创建hashmap
fn test1() {
// let mut m = BTreeMap::new(); //std::collections::hash::map::BTreeMap<i32, i32>
let mut m:BTreeMap<i32,i32> = BTreeMap::new(); //std::collections::hash::map::BTreeMap<i32, i32>
m.insert(0,1);
m.insert(2,3);
print_type_of(&m);
//为什么key和v都是i32的类型?
//这里m不使用引用,就会获取m的所有权,后面将不能再使用m
//不使用引用,k,v都是i32,m使用引用,k,v都是&i32
for (k,v) in &m {
println!("{} {}",k,v);
print_type_of(&v);
print_type_of(&k);
}
println!("{}",m.contains_key(&2));
}
//hashmap常规使用
fn test2() {
let range = 0..5;
// let mut m:BTreeMap<i32,i32> = range.map(|i|(i,i+1)).collect();
let mut m = BTreeMap::from([
(0,1),(1,2),(2,3),(3,4),(4,5)
]);
m.insert(5,7);
print_type_of(&m); //std::collections::hash::map::BTreeMap<i32, i32>
println!("len: {}",m.len());
// println!("capacity: {}",m.capacity());
//输出是无序的
for (k,v) in &m {
println!("k: {},v: {}",k,v);
print_type_of(&k);
print_type_of(&v);
}
//查询是否包含指定key
println!("{}",m.contains_key(&7)); //false
println!("{}",m.contains_key(&5)); //true
//获取指定key的value
println!("{:?}",m.get(&7)); //None
println!("{:?}",m.get(&5)); //Some(7)
let mut five = m.get_mut(&5);
// let mut num = 999; //这样改是没有用的,必须在模式匹配中才有效
// five.replace(&mut num);
match five {
Some(ref mut v) => {
**v = 999;
print_type_of(&v); //&mut &mut i32
},
_ =>{},
}
println!("{}",m[&5]); //999
//移除指定key
println!("{:?}",m.remove(&7)); //None
println!("{:?}",m.remove(&5)); //Some(999)
print_type_of(&m.remove_entry(&3)); //core::option::Option<(i32, i32)>
println!("{:?}",m.remove_entry(&2));//Some((2, 3))
print_type_of(&m.get_key_value(&1)); //core::option::Option<(&i32, &i32)>
println!("{:?}",m.get_key_value(&1)); //Some((1, 2)),自动解引用了
//直接通过索引找key,找不存在的key就会panic
println!("{}",m[&5]); //no entry found for key,然后panic
}
// type func = fn()->i32; //这样定义的用处是什么呢
fn get_five() ->i32 {
5
}
//map中entry的用法
fn test3() {
let range = 0..6;
// let mut m:BTreeMap<i32,i32> = range.map(|i|(i,i+2)).collect();
let mut m:BTreeMap<i32,i32> = (0..6).map(|i|(i,i+2)).collect();
// print_type_of(&m.entry(0));
println!("len {}",m.len());
//最好是不要创建变量来调用m.entry(),e的每次调用都会消耗掉所有权,从而需要重新调用m.entry()
/*let e = m.entry(10);
print_type_of(&e); //Enum std::collections::hash_map::Entry std::collections::hash::map::Entry<i32, i32>
e.or_insert(100); //不存在的key,就会创建并插入
// let e = m.entry(10);
println!("{}",e.or_insert(100));
// let e = m.entry(10);
*e.or_insert(100) = 66;
// let e = m.entry(10);
println!("{}",e.or_insert(100));
return;*/
//or_insert(v) 直接插入一个值
/*
m.entry(10).or_insert(100);
println!("len {}",m.len()); //长度增加了
println!("{:?}",m.entry(10));
*m.entry(10).or_insert(66) = 66;
println!("{:?}",m.entry(10));
*/
//or_insert_with(||v) 利用闭包来创建插入的值
/*
m.entry(10).or_insert_with(||100);
println!("len {}",m.len()); //长度增加了
println!("{:?}",m.entry(10));
*m.entry(10).or_insert_with(||100) = 66;
println!("{:?}",m.entry(10));
*/
/*fn Six()->i32 {
6
}
// let six = || 6;
// let six = ||->i32 {6};
m.entry(10).or_insert_with(Six);
// m.entry(10).or_insert_with(get_five); //闭包也行,函数也行
println!("len {}",m.len()); //长度增加了
println!("{:?}",m.entry(10));
*m.entry(10).or_insert_with(||100) = 66;
println!("{:?}",m.entry(10));
*/
// return;
//这样使用,就像最开始创建m时,根据k,生成v
m.entry(10).or_insert_with_key(|k|k+2);
println!("{:?}",m.entry(10));
println!("len {}",m.len()); //长度增加了
*m.entry(10).or_insert_with_key(|k|k+2) = 66;
println!("{:?}",m.entry(10));
m.entry(10).and_modify(|e| *e*=10); //and_modify,只能在entry存在时,进行修改
println!("{:?}",m.entry(10));
m.entry(100).and_modify(|e| *e*=10); //and_modify,entry不存在时
println!("{:?}",m.entry(100)); //Entry(VacantEntry(100))
m.entry(100).or_default();
println!("{:?}",m.entry(100)); //插入了i32的默认值,为0
*m.entry(100).or_default() = 166;
println!("{:?}",m.entry(100));
/*
//entry,使用后会消耗
let e = m.entry(100);
let v = e.or_default();
*v = 166;
println!("{:?}",m.entry(100));
let e = m.entry(100);
let v = e.or_insert(66);
*v = 188;
println!("{:?}",m.entry(100));
*/
}
fn test4() {
let mut m = BTreeMap::from([
("a",1),("b",2),("c",3)
]);
//m.keys(),返回键的引用
for k in m.keys() {
println!("{}",k);
print_type_of(&k); //&&str
}
/*
//into_keys(),将获取m的所有权
let keys:Vec<_> = m.into_keys().collect(); //会消耗m,m将失去所有权
print_type_of(&keys); //alloc::vec::Vec<&str>
println!("{:?}",keys); //["a", "b", "c"]
// print_type_of(&m); //不能再使用m
*/
//m.values_mut(),返回值的可变引用
for v in m.values_mut() {
*v *=10;
print_type_of(&v); //&mut i32
}
//m.values(),返回值的引用
for v in m.values() {
println!("{}",v);
print_type_of(&v); //&i32
}
/*
//into_values(),将获取m的所有权
let values:Vec<_> = m.into_values().collect();
print_type_of(&values); //alloc::vec::Vec<i32>
println!("{:?}",values);
// print_type_of(&m); //不能再使用m
*/
//不加&也会获取m的所有权
for (k,v) in &m {
println!("{} {}",k,v);
print_type_of(&k);
print_type_of(&v);
break;
}
print_type_of(&m); //遍历不加&就不能再使用m
//k和v都是引用,但是v可变
for (_,v) in m.iter_mut() {
*v +=16;
print_type_of(&v); //&mut i32
}
//使用m.iter(),效果和&m一致
for (k,v) in m.iter() {
println!("{} {}",k,v);
print_type_of(&k);
print_type_of(&v);
break;
}
print_type_of(&m);
println!("{:?}",m); //{"c": 46, "a": 26, "b": 36}
//k:&&str,v:&mut i32同迭代器,都是引用
//同模式匹配一直,这里可以是ref k ,k,&k ,k的类型分别是&&&str,&&str,&str
//原地操作,删除返回false的key-value
m.retain(|k,v|{
print_type_of(&k);
print_type_of(&v);
if v==&36 || *v == 36 {
*v = 999;
}
true
});
println!("{:?}",m); //{"c": 46, "a": 26, "b": 36}
let cm:Vec<_> = m.clone().into_iter().collect();
print_type_of(&cm); //alloc::vec::Vec<(&str, i32)>
println!("{:?}",cm); //[("a", 26), ("b", 999), ("c", 46)]
print_type_of(&m.clone().into_iter()); //std::collections::hash::map::IntoIter<&str, i32>
print_type_of(&m.iter()); //std::collections::hash::map::Iter<&str, i32>
print_type_of(&m.iter_mut()); //std::collections::hash::map::IterMut<&str, i32>
// println!("{}",m.capacity());
// m.clear(); //容量还在,但是数据清除了
// println!("{}",m.capacity());
}
fn main() {
test4();
}
代码和HashMap几乎没有什么不同,就是没有capacity()了,需要注释掉
3.HashSet
#![feature(hash_set_entry)]
use std::collections::HashSet;
use std::any::type_name;
//输出变量类型
fn print_type_of<T>(_: &T) {
println!("{}", type_name::<T>());
}
fn value(mut v:i32) ->i32{
v = v*10 + 1;
v
}
fn test() {
// let mut s:HashSet<i32> = (0..11).map(|mut v|{
// v*=10;
// v
// }).collect();
//闭包里面,直接给一个函数也是可以的
let h = value;
print_type_of(&value);
let mut s:HashSet<i32> = (0..11).map(h).collect();
//let mut s:HashSet<i32> = (0..11).map(value).collect();
println!("{:?}",s);
}
fn main() {
// let mut s = HashSet::new();
// let mut s = HashSet::with_capacity(5);
let mut s = HashSet::from([1,2,3,4,5,6]);
// s.insert(5);
// s.insert(6);
print_type_of(&s);
println!("{:?}",s);
//^ value borrowed here after move,遍历时不使用引用也会获取所有权
for v in &s {
print_type_of(&v);
println!("{}",v);
}
//二者的遍历效果是一致的,但是iter()不会带走所有权
println!("-----------");
//retain的参数也是引用,也可以使用ref v,v,&v,分别是&&i32,&i32,i32
s.retain(|v|{
print_type_of(&v);
*v>=3 //删掉<3的元素
});
println!("移除3 {}",s.remove(&3));//true
for v in s.iter() {
print_type_of(&v);
println!("{}",v);
}
println!("{}",s.contains(&5));
println!("{:?}",s.get(&6)); //Some(6)
println!("{:?}",s.get(&10)); //None
println!("{}",s.get_or_insert(10)); //实验性的,要在顶上添加 #![feature(hash_set_entry)]
print_type_of(&s.get_or_insert(10)); //&i32
// println!("{}",s.get_or_insert_with(&100,|_|66)); //测试失败
println!("{}",s.len());
println!("{:?}",s);
println!("----------");
println!("first replace 50 {:?}",s.replace(50)); //没有,就返回Some(50),然后插入,有,就和s.get(&50)一样了
println!("second replace 50 {:?}",s.replace(50)); //Some(50)
println!("{:?}",s.get(&50)); //Some(50)
println!("{:?}",s.take(&50)); //有,就删除,并返回Some(50),没有,就是None
println!("{:?}",s.take(&50)); //None
//插入一下Option的take和replace方法
{
let mut a = Some(188);
println!("{:?}",a); //Some(188)
let b = a.take(); //有,就拿走,a就变成None
println!("{:?}",b); //Some(188)
println!("{:?}",a); //None
println!("{:?}",a.take()); //None
let c = a.replace(166); //c变成a原来的值,a变成新的值
println!("{:?}",a); //Some(166)
println!("{:?}",c); //None
let c = a.replace(721);
println!("{:?}",a); //Some(721)
println!("{:?}",c); //Some(166)
}
println!("---------");
println!("{:?}",s);
let set:HashSet<i32> = (1..11).map(|v|v).collect();
println!("{:?}",set);
println!("{}",s.is_subset(&set)); //s是否是set的子集
println!("{}",set.is_superset(&s)); //set是否是s的超集
println!("{}",s.is_disjoint(&set)); //有无交集,有
let s1 = HashSet::from([99,98,100]);
println!("{}",s1.is_disjoint(&set)); //有无交集,无
s.insert(99);
s.insert(98);
println!("{:?}",s.difference(&s1)); //s去掉和s1相交的部分
println!("{:?}",s1.difference(&s)); //s1去掉和s相交的部分
//效果就像是两个集合都去掉重叠的部分,然后合并
println!("{:?}",s.symmetric_difference(&s1));
println!("{:?}",s1.symmetric_difference(&s));
println!("{:?}",s.intersection(&s1)); //求交集
println!("{:?}",s.union(&s1)); //求并集
//清除后,就是空的了
// s.clear();
// println!("{}",s.is_empty());
}
4.BTreeSet
使用起来和HashSet没有太大区别,除了键是有序的,并且没有get_or_insert()德国方法
#![feature(hash_set_entry)]
use std::collections::BTreeSet;
use std::any::type_name;
//输出变量类型
fn print_type_of<T>(_: &T) {
println!("{}", type_name::<T>());
}
fn main() {
// let mut s = BTreeSet::new();
// let mut s = BTreeSet::with_capacity(5);
let mut s = BTreeSet::from([1,2,3,4,5,6]);
// s.insert(5);
// s.insert(6);
print_type_of(&s);
println!("{:?}",s);
//^ value borrowed here after move,遍历时不使用引用也会获取所有权
for v in &s {
print_type_of(&v);
println!("{}",v);
}
//二者的遍历效果是一致的,但是iter()不会带走所有权
println!("-----------");
//retain的参数也是引用,也可以使用ref v,v,&v,分别是&&i32,&i32,i32
s.retain(|v|{
print_type_of(&v);
*v>=3 //删掉<3的元素
});
println!("移除3 {}",s.remove(&3));//true
for v in s.iter() {
print_type_of(&v);
println!("{}",v);
}
println!("{}",s.contains(&5));
println!("{:?}",s.get(&6)); //Some(6)
println!("{:?}",s.get(&10)); //None
//并没有get_or_insert()方法
// println!("{}",s.get_or_insert(10)); //实验性的,要在顶上添加 #![feature(hash_set_entry)]
// print_type_of(&s.get_or_insert(10)); //&i32
// println!("{}",s.get_or_insert_with(&100,|_|66)); //测试失败
println!("{}",s.len());
println!("{:?}",s);
println!("----------");
println!("first replace 50 {:?}",s.replace(50)); //没有,就返回Some(50),然后插入,有,就和s.get(&50)一样了
println!("second replace 50 {:?}",s.replace(50)); //Some(50)
println!("{:?}",s.get(&50)); //Some(50)
println!("{:?}",s.take(&50)); //有,就删除,并返回Some(50),没有,就是None
println!("{:?}",s.take(&50)); //None
//插入一下Option的take和replace方法
{
let mut a = Some(188);
println!("{:?}",a); //Some(188)
let b = a.take(); //有,就拿走,a就变成None
println!("{:?}",b); //Some(188)
println!("{:?}",a); //None
println!("{:?}",a.take()); //None
let c = a.replace(166); //c变成a原来的值,a变成新的值
println!("{:?}",a); //Some(166)
println!("{:?}",c); //None
let c = a.replace(721);
println!("{:?}",a); //Some(721)
println!("{:?}",c); //Some(166)
}
println!("---------");
println!("{:?}",s);
let set:BTreeSet<i32> = (1..11).map(|v|v).collect();
println!("{:?}",set);
println!("{}",s.is_subset(&set)); //s是否是set的子集
println!("{}",set.is_superset(&s)); //set是否是s的超集
println!("{}",s.is_disjoint(&set)); //有无交集,有
let s1 = BTreeSet::from([99,98,100]);
println!("{}",s1.is_disjoint(&set)); //有无交集,无
s.insert(99);
s.insert(98);
println!("{:?}",s.difference(&s1)); //s去掉和s1相交的部分
println!("{:?}",s1.difference(&s)); //s1去掉和s相交的部分
//效果就像是两个集合都去掉重叠的部分,然后合并
println!("{:?}",s.symmetric_difference(&s1));
println!("{:?}",s1.symmetric_difference(&s));
println!("{:?}",s.intersection(&s1)); //求交集
println!("{:?}",s.union(&s1)); //求并集
//清除后,就是空的了
// s.clear();
// println!("{}",s.is_empty());
}
标签:map,set,mut,print,let,println,entry,type,rust
From: https://www.cnblogs.com/dayq/p/18516618