向量
就像我们有&str
和String
一样,我们有数组和向量。数组的功能少了就快,向量的功能多了就慢。(当然,Rust的速度一直都是非常快的,所以向量并不慢,只是比数组慢一点)。类型写成Vec
,你也可以直接叫它 "vec"。
向量的声明主要有两种方式。一种是像String
一样使用new
:
fn main() { let name1 = String::from("Windy"); let name2 = String::from("Gomesy"); let mut my_vec = Vec::new(); // If we run the program now, the compiler will give an error. // It doesn't know the type of vec. my_vec.push(name1); // Now it knows: it's Vec<String> my_vec.push(name2); }
你可以看到Vec
里面总是有其他东西,这就是<>
(角括号)的作用。Vec<String>
是一个有一个或多个String
的向量。你还可以在里面有更多的类型。比如说
Vec<(i32, i32)>
这是一个Vec
其中每个元素是一个元组。(i32, i32)
.Vec<Vec<String>>
这是一个Vec
,其中有Vec
的Strings
。比如说你想把你喜欢的书保存为Vec<String>
。然后你再用另一本书来做,就会得到另一个Vec<String>
。为了保存这两本书,你会把它们放入另一个Vec
中,这就是Vec<Vec<String>>
。
与其使用 .push()
让 Rust 决定类型,不如直接声明类型。
fn main() { let mut my_vec: Vec<String> = Vec::new(); // The compiler knows the type // so there is no error. }
你可以看到,向量中的元素必须具有相同的类型。
另一个创建向量的简单方法是使用 vec!
宏。它看起来像一个数组声明,但前面有 vec!
。
fn main() { let mut my_vec = vec![8, 10, 10]; }
类型是Vec<i32>
。你称它为 "i32的Vec"。而Vec<String>
是 "String的Vec"。Vec<Vec<String>>
是 "String的Vec的Vec"。
你也可以对一个向量进行分片,就像在数组中一样。
fn main() { let vec_of_ten = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // Everything is the same as above except we added vec!. let three_to_five = &vec_of_ten[2..5]; let start_at_two = &vec_of_ten[1..]; let end_at_five = &vec_of_ten[..5]; let everything = &vec_of_ten[..]; println!("Three to five: {:?}, start at two: {:?} end at five: {:?} everything: {:?}", three_to_five, start_at_two, end_at_five, everything); }
因为Vector比数组慢,我们可以用一些方法让它更快。一个vec有一个容量,也就是给向量的空间。当你在向量上推送一个新的元素时,它会越来越接近容量。然后,如果你超过了容量,它将使其容量翻倍,并将元素复制到新的空间。这就是所谓的重新分配。我们将使用一种名为.capacity()
的方法来查看向量的容量,在我们向它添加元素时。
例如,我们将使用名为.capacity()
的方法来观察一个向量的容量。
fn main() { let mut num_vec = Vec::new(); println!("{}", num_vec.capacity()); // 0 elements: prints 0 num_vec.push('a'); // add one character println!("{}", num_vec.capacity()); // 1 element: prints 4. Vecs with 1 item always start with capacity 4 num_vec.push('a'); // add one more num_vec.push('a'); // add one more num_vec.push('a'); // add one more println!("{}", num_vec.capacity()); // 4 elements: still prints 4. num_vec.push('a'); // add one more println!("{}", num_vec.capacity()); // prints 8. We have 5 elements, but it doubled 4 to 8 to make space }
这个打印:
0
4
4
8
所以这个向量有两次重分配: 0到4,4到8。我们可以让它更快:
fn main() { let mut num_vec = Vec::with_capacity(8); // Give it capacity 8 num_vec.push('a'); // add one character println!("{}", num_vec.capacity()); // prints 8 num_vec.push('a'); // add one more println!("{}", num_vec.capacity()); // prints 8 num_vec.push('a'); // add one more println!("{}", num_vec.capacity()); // prints 8. num_vec.push('a'); // add one more num_vec.push('a'); // add one more // Now we have 5 elements println!("{}", num_vec.capacity()); // Still 8 }
这个向量有0个重分配,这是比较好的。所以如果你认为你知道你需要多少元素,你可以使用Vec::with_capacity()
来使它更快。
你记得你可以用.into()
把&str
变成String
。你也可以用它把一个数组变成Vec
。你必须告诉 .into()
你想要一个 Vec
,但你不必选择 Vec
的类型。如果你不想选择,你可以写Vec<_>
。
fn main() { let my_vec: Vec<u8> = [1, 2, 3].into(); let my_vec2: Vec<_> = [9, 0, 10].into(); // Vec<_> means "choose the Vec type for me" // Rust will choose Vec<i32> }