Skip to content

Vec::len

Vec methods · Collections

Level: reference · for working programmers

One line: How many elements are in the vector.

pub const fn len(&self) -> usize

Stable since 1.0.0. Callable in a const context since 1.87.0.

A field read, not a walk — O(1) — so calling it in a loop condition costs nothing.

It counts elements, not bytes. For a Vec<u8> those happen to be the same number; for a Vec<u64> the byte count is len() * 8. (String::len counts bytes, which is the reverse trap.)

len is not capacity: one is what is there, the other what fits.

The last valid index is len() - 1, and on an empty vector that underflows, because usize has no −1. v.last(), v.first() and v.get(i) return Option and sidestep it entirely; checked_sub(1) is the explicit version.

len() == 0 should be written is_empty()clippy::len_zero is warn-by-default about exactly that.

On a Vec<Vec<T>>, len is the outer count. Total cells is v.iter().map(Vec::len).sum().

Example

vec_len.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let v = vec![10, 20, 30];
    println!("len {}", v.len());

    // len counts ELEMENTS. For a Vec<u8> that happens to equal the byte
    // count; for anything else it does not.
    let bytes: Vec<u8> = vec![1, 2, 3, 4];
    let words: Vec<u64> = vec![1, 2, 3, 4];
    println!("both len 4: {} {} — but {} bytes vs {} bytes",
             bytes.len(), words.len(),
             bytes.len() * size_of::<u8>(), words.len() * size_of::<u64>());

    // len is not capacity. One is what is there, the other what fits.
    let mut v: Vec<i32> = Vec::with_capacity(10);
    v.push(1);
    println!("len {} capacity {}", v.len(), v.capacity());

    // It is O(1) — a field read, not a walk — so calling it in a loop
    // condition costs nothing.
    let v = vec![0u8; 5];
    let mut total = 0;
    for i in 0..v.len() { total += i; }
    println!("index sum {total}");

    // The last valid index is len - 1, which is why the empty case needs
    // care: 0 - 1 underflows on usize.
    let v: Vec<i32> = vec![];
    println!("last index of an empty vec: {:?}", v.len().checked_sub(1));
    println!("prefer .last(): {:?}", v.last());

    // is_empty() is len() == 0, and reads better.
    let v = vec![1];
    println!("{} {}", v.len() == 0, v.is_empty());

    // Nested: len is the outer count only.
    let grid = vec![vec![1, 2, 3], vec![4, 5]];
    println!("rows {} total cells {}", grid.len(),
             grid.iter().map(|r| r.len()).sum::<usize>());
}

Verified output of vec_len.rs — regenerated by tools/run_examples.py, never hand-typed.

len 3
both len 4: 4 4 — but 4 bytes vs 32 bytes
len 1 capacity 10
index sum 10
last index of an empty vec: None
prefer .last(): None
false false
rows 2 total cells 5

See also

Vec::len in the standard library ↗