向量

就像我们有&strString一样,我们有数组和向量。数组的功能少了就快,向量的功能多了就慢。(当然,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,其中有VecStrings。比如说你想把你喜欢的书保存为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>
}