rust练习-集合、trait
关联类型
关联函数
定义在impl
中且没有self
的函数称为关联函数。
demo:
#![allow(unused)]
fn main() {
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn new(w: u32, h: u32) -> Rectangle {
Rectangle { width: w, height: h }
}
}
}
关联类型
在特征定义的语句块中,申明一个自定义类型,然后再特征的方法签名中使用。
pub trait Iterator {
type Item;
// Self用来指代当前调用者的具体类型
fn next(&mut self) -> Option<Self::Item>;
}
pub struct Counter;
impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
fn main() {
let mut c = Counter{};
c.next();
}
泛型:
pub trait Iterator<Item> {
// Self用来指代当前调用者的具体类型
fn next(&mut self) -> Option<Self::Item>;
}
泛型和关联类型对比
泛型
trait Container<A,B> {
fn contains(&self,a: A,b: B) -> bool;
}
fn difference<A,B,C>(container: &C) -> i32
where
C : Container<A,B> {...}
}
关联类型
trait Container{
type A;
type B;
fn contains(&self, a: &Self::A, b: &Self::B) -> bool;
}
fn difference<C: Container>(container: &C) {}
默认类型参数
// 语法, rhs: right hand side
trait Add<RHS=Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
// demo:
use std::ops::Add;
struct Millimeters(u32);
struct Meters(u32);
impl Add<Meters> for Millimeters {
type Output = Millimeters;
fn add(self, other: Meters) -> Millimeters {
Millimeters(self.0 + (other.0 * 1000))
}
}
泛型类型参数
use std::ops::Sub;
#[derive(Debug, PartialEq)]
struct Point<T> {
x: T,
y: T,
}
// 用三种方法填空: 其中两种使用默认的泛型参数,另外一种不使用
impl<T: Sub<Output=T>> Sub<Self> for Point<T> {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
Point {
x: self.x - other.x,
y: self.y - other.y,
}
}
}
fn main() {
assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 },
Point { x: 1, y: 3 });
println!("Success!")
}
String设置初始大小
let mut s = String::with_capacity(25);
Vec
vector获取值
// 修复错误并实现缺失的代码
fn main() {
let mut v = Vec::from([1, 2, 3]);
for i in 0..5 {
println!("{:?}", v.get(i))
}
for i in 0..5 {
// 实现这里的代码...
match v.get(i) {
Some(_) => {
v[i] += 1;
},
None => {
v.push(i+2);
}
}
}
assert_eq!(v, vec![2, 3, 4, 5, 6]);
println!("Success!")
}
Some(1)
Some(2)
Some(3)
None
None
Success!
切片和引用
切片和 `&Vec` 是不同的类型,后者仅仅是 `Vec` 的引用,
并可以通过解引用直接获取 `Vec`
HashMap
一些基本使用

collect
use std::collections::HashMap;
fn main() {
let teams = [
("Chinese Team", 100),
("American Team", 10),
("France Team", 50),
];
let mut teams_map1 = HashMap::new();
for team in &teams {
teams_map1.insert(team.0, team.1);
}
// 使用两种方法实现 team_map2
// 提示:其中一种方法是使用 `collect` 方法
// 和iter的区别
// let teams_map2 = HashMap::from(teams);
let teams_map2: HashMap<_,_> = teams.into_iter().collect();
assert_eq!(teams_map1, teams_map2);
println!("Success!")
}
or_insert
// 填空
use std::collections::HashMap;
fn main() {
// 编译器可以根据后续的使用情况帮我自动推断出 HashMap 的类型,当然你也可以显式地标注类型:HashMap<&str, u8>
let mut player_stats = HashMap::new();
// 查询指定的 key, 若不存在时,则插入新的 kv 值
player_stats.entry("health").or_insert(100);
assert_eq!(player_stats["health"], 100);
// 通过函数来返回新的值
player_stats.entry("health").or_insert_with(random_stat_buff);
assert_eq!(player_stats["health"], 100);
let health = player_stats.entry("health").or_insert(50);
assert_eq!(*health, 100);
*health -= 50;
assert_eq!(*health, 50);
println!("Success!")
}
fn random_stat_buff() -> u8 {
// 为了简单,我们没有使用随机,而是返回一个固定的值
42
}
Eq PartialEq
如果我们想比较某个类型的两个值 x 和 y 是否相等(不等),例如:x == y (x != y),那么我们就必须为类型实现 PartialEq Trait。
PartialEq 可使用 #[derive] 来交由编译器实现,当一个 struct 在进行相等比较时,会对其中每一个字段进行比较;如果遇到枚举时,还会对枚举所拥有的数据进行比较。
实现 Eq 的前提是已经实现了 PartialEq,因为实现 Eq 不需要额外的代码,只需要在实现了PartialEq 的基础上告诉编译器它的比较满足自反性就可以了。