Vec<T> in Depth

append() and extend()

Vec<T> provides three bulk-appending methods—.append(&mut other), .extend(iter), and .extend_from_slice(slice)—that add multiple elements to the back of a vector while reserving the required capacity upfront.

Comparison of Bulk-Appending Methods

Method Signature What Happens to the Source? Trait Bounds
v.append(&mut other) fn append(&mut self, other: &mut Vec<T>) Moves all elements out of other, leaving other empty (other.len() == 0) while keeping other's heap capacity None (T: Sized)
v.extend(iter) fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) Consumes iter (Vec<T>, array, range, or adapter chain) and appends each item None (or T: Copy when extending from Iterator<Item = &T>)
v.extend_from_slice(s) fn extend_from_slice(&mut self, other: &[T]) Borrows other: &[T] and clones each element onto self (memcpy for Copy types) T: Clone
v.extend_from_within(r) fn extend_from_within<R: RangeBounds<usize>>(&mut self, src: R) Clones a subrange of self and appends it to the end of self T: Clone
v.append(&mut other):
  Before: v = [1, 2],       other = [3, 4] (cap = 4)
  After:  v = [1, 2, 3, 4], other = []     (cap = 4, reusable!)

Moving Elements Between Vectors with append()

Because v.append(&mut other) transfers elements in a single contiguous ptr::copy_nonoverlapping block and sets other.len = 0 without dropping other's allocation, it is ideal when other is a reusable scratch buffer in a loop:

fn main() {
    let mut main_batch = vec![String::from("job-1"), String::from("job-2")];
    let mut worker_batch = vec![String::from("job-3"), String::from("job-4")];

    main_batch.append(&mut worker_batch);

    println!("main_batch:   {main_batch:?}");
    println!(
        "worker_batch: {worker_batch:?} (len={}, cap={})",
        worker_batch.len(),
        worker_batch.capacity()
    );
}
main_batch:   ["job-1", "job-2", "job-3", "job-4"]
worker_batch: [] (len=0, cap=2)

Appending Iterators and Slices with extend() and extend_from_slice()

fn main() {
    let mut nums = vec![1, 2];

    // 1. Append from any IntoIterator (such as a range or mapped iterator):
    nums.extend(3..=5);

    // 2. Append from a borrowed slice `&[i32]`:
    let tail = [6, 7, 8];
    nums.extend_from_slice(&tail);

    // 3. Duplicate the first 3 elements (`0..3`) onto the end of `nums`:
    nums.extend_from_within(0..3);

    println!("nums: {nums:?}");
}
nums: [1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3]