《Rust权威指南》学习笔记之第8章 通用集合类型

130 篇文章 4 订阅
9 篇文章 0 订阅

集合数据类型,数据存储在堆上,可以增删。

  • 动态数组(vector)可以连续存储任意多个相同类型的值。
  • 字符串(string)是字符的集合。
  • 哈希映射(hash map)值关联到特定键上,映射(map)的特殊实现。

动态数组

Vec<T>

创建

let v: Vec<i32> = Vec::new();

let v = vec![1, 2, 3];

更新

let mut v = Vec::new();
v.push(5);
v.push(6);
v.push(7);
v.push(8);

销毁

{
	let v = vec![1, 2, 3, 4];
}

读取动态数组中的元素

let v = vec![1, 2, 3, 4, 5];

let third: &i32 = &v[2];
println!("The third element is {}", third);

match v.get(2) {
	Some(third) => println!("The third element is {}", third),
	None => println!("There is no third element.", third),
}
let v = vec![1, 2, 3, 4, 5];

let does_not_exist = &v[100];	//panic
let does_not_exist = v.get(100);	//None
let mut v = vec![1, 2, 3, 4, 5];

let first = &v[0];	//不可变引用
v.push(6);	//可变引用
println!("The first element is {}", first);//error

遍历

let v = vec![100, 32, 57];
for i in &v {
	println!("{}", i);
}
let mut v = vec![100, 32, 57];
for i in &mut v {
	*i += 50;;
}

枚举存储多个类型值

enum SpreadsheetCell {
	Int(i32),
	Float(f64),
	Text(String),
}

let row = vec![
	SpreadsheetCell::Int(3),
	SpreadsheetCell::Text(String::from("blue")),
	SpreadsheetCell::Float(10.12),
]

字符串存储UTF-8文本

字符串基于字节的集合,使用UTF-8编码.

字符串是什么

核心部分只有一种字符串类型,字符串切片str,常以借用形式&str出现。
标准库中String,OsString,OsStr, CString, CStr。

创建新字符串

let mut s = String::new();

let data = "initial contents"; //&str
let s = data.to_string();

let s = "initial contents".to_string();
let s = String::from("initial contents");

更新字符串

let mut s1 = String::from("foo");
let s2 = "bat"
s1.push_str(s2);
println!("s2 is {}", s2);

s1.push('1');
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; //s1已被移动
//fn add(self, s: &str) -> String

编译器可以自动将&String类型的参数强制转换为&str类型,解引用强制转换技术,将&s2转换为了&s2[…]。

let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("tce");

//不会夺取任何参数的所有权
let s = format!("{}-{}-{}", s1, s2, s3);

字符串索引

let s1 = String::from("hello");
let h = s1[0]; 	//错误,Rust字符串不支持索引

内部布局

String是基于Vec<u8>的封装类型。
let len = String::from(“Hola”).len(); //4
let len = String::from(“你好”).len(); //?

字节、标量值及字形簇

字符串切片

let s1 = String::from("hello");
let h = &s1[0..4]; 	

遍历字符串

for c in "你好world".chars() {
	println!("{}", c);
}
for b in "你好world".bytes() {
	println!("{}", b);
}

哈希映射中存储键值对

HashMap<K, V>,内部实现中使用了哈希函数。哈希(hash)、映射(map)、对象(object)、哈希表(hash table)、字典(dictionary)、关联数组(associative array)等。所有键相同类型,所有值相同类型。

创建哈希映射

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
use std::collections::HashMap;

let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];

let scores: HashMap<_, _> = teams.iter().zip(initial_scores.iter()).collect();

哈希映射与所有权

实现了Copy trait类型,如i32,值会被简单复制;String这种持有所有权类型,值和所有权会被转移给哈希映射。

use std::collections::HashMap;

let field_name = String::from("Favorite color");
let field_value = String::from("Blue");

let mut map = HashMap::new();
map.insert(field_name, field_value);
//field_name和field_value失效。

引用插入哈希映射,不会被移动。这些引用所指向的值必须要保证,在哈希映射有效时自己也是有效的。

访问哈希映射中的值

use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);

    let team_name = String::from("Blue");
    let score = scores.get(&team_name);

    match score {
        None => println!("None"),
        Some(i) => println!("{}", i),
    }

    for (key, value) in &scores {
    	println!("{}: {}", key, value);
    }
    println!("Hello, world!");
}

更新哈希映射

覆盖旧值

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Blue"), 25);

println!("{:?}", scores);

只在键无值时插入数据

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);

scores.entry(String::from("Yellow")).or_insert(50);
scores.entry(String::from("Blue")).or_insert(50);

println!("{:?}", scores);

基于旧值来更新值

use std::collections::HashMap;

let text = "hello world wonderful world";

let mut map = HashMap::new();

for word in text.split_whitespace() {
	let count = map.entry(word).or_insert(0);
	*count += 1;
}

println!("{:?}", scores);

哈希函数

为了提供抵御拒绝服务攻击(DoS,Denial of Service)的能力,HashMap使用了默认哈希函数。可以通过实现BuildHasher trait的类型,自定义哈希函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值