When to use Arrays and Vectors in Rust — Array[] vs Vectors<>

by Ugochukwu Chizaram Omumusinachi

.

Updated Thu Jan 30 2025

When to use Arrays and Vectors in Rust — Array[] vs Vectors<>

What is the difference between arrays and vectors in Rust? The answer is: They are both fundamentally the same thing, trust me bro 🫠*. Same same but different.*

You see to understand the difference between rust arrays and vectors we have to look back into Data structures. What is an Array (or list if you come from a Python background)?

In short terms, an array is a contiguous data structure stored on the stack. Now if you did your homework you would know there a two major types of arrays, Dynamic and Static Arrays.

This article is not about Data Structures in general so I won’t go into details, but all you have to know is Dynamic arrays are simply static arrays with a bunch of wrappers to handle fluidity, in rust this wrapper is called a Vector.

So, fundamentally they are both the same thing, with slight implementation differences. These differences and trade-offs as well as special features as well as some guidelines for usage as some of the things you should know by the time we are done here.

💡 Vectors are Dynamic Arrays while Arrays are Static Arrays.

Now we are over with the introduction, let's get into some details.

First: Definition and Basic Syntax

Arrays

  • Fixed-size: Size determined at compile time.

  • Stack-allocated: Memory lives on the stack.

  • Type signature[T; N], where T is the element type and N is a compile-time constant.

// Declare an array of 5 integers
let arr: [i32; 5] = [1, 2, 3, 4, 5];

// Initialize all elements to 0
let zeros = [0; 10]; // Array of 10 zeros

Vectors

  • Dynamic size: Can grow or shrink at runtime.

  • Heap-allocated: Memory is managed dynamically on the heap.

  • Type signatureVec<T>.

// Create a vector with initial values
let mut vec = vec![1, 2, 3];

// Add elements dynamically
vec.push(4); // Now contains [1, 2, 3, 4]

Key Differences

Now we know how to define both structures and you know how to identify each of them in code, and how they are handled by your computer, we should now know the differences.

Feature

Arrays ([T; N])

Vectors (Vec<T>)

Size

Fixed at compile time.

Dynamic (can resize at runtime).

Memory Allocation

Stack-allocated.

Heap-allocated.

Mutability

The entire array is immutable/mutable.

Individual elements or sizes can be changed.

Performance

Faster access (no heap overhead).

Slightly slower due to heap management.

Methods

Limited functionality.

Rich API (pushpopinsert, etc.). It's a wrapper after all.

Memory and Ownership

Arrays

  • Stack-bound: Memory is contiguous and allocated when the array is declared.

  • Fixed ownership: The entire array is moved or borrowed as a single unit.

  • Slices: To borrow some part of an array you can use a slice

fn print_array(arr: [i32; 3]) {
    println!("{:?}", arr);
}

let a = [1, 2, 3];
print_array(a); // Ownership of `a` is moved

Vectors

  • Heap flexibility: Data lives on the heap, but the vector itself (pointer, capacity, length) is stored on the stack.

  • Mutable borrowing: Allows partial mutation (e.g., modify elements without moving the entire vector).

fn double_elements(vec: &mut Vec<i32>) {
    for num in vec.iter_mut() {
        *num *= 2;
    }
}

let mut v = vec![1, 2, 3];
double_elements(&mut v); // Mutably borrows `v`

Common Operations

Array Operations

  • Accessing elements:

let arr = [10, 20, 30];
let first = arr[0]; // 10
  • Iteration:

    for num in arr.iter() {
        println!("{}", num);
    }
    
  • Limitations: Since the size is fixed you cannot push or pop unlike in vectors

Vector Operations

  • Adding/removing elements:

    let mut vec = vec![1, 2];
    vec.push(3); // [1, 2, 3]
    vec.pop();   // [1, 2]
    
  • Resizing:

    vec.resize(5, 0); // [1, 2, 0, 0, 0]
    
  • Slicing:

    let slice = &vec[1..3]; // [2]
    

Conversion Between Arrays and Vectors

You might find yourself in a situation where for some reason you want to convert from an array to a vector. Here is how to do it:

Array to Vector:

By calling the to_vec() inbuilt method, you effectively create a Vector type from the contents of your arrays, the array is then dropped and the handles for it are now switched to a Vector instead

let arr = [1, 2, 3];
let vec = arr.to_vec(); // Converts to Vec<i32>

Vector to Array

On the other hand, to convert from a vector to an array (to be honest I do not know how you found yourself doing this ) you would need to call the try_into trait method.

This trait method would try to convert one type to another, luckily the trait Into array is implemented for Vectors. This operation is fallible — meaning it returns a result — so you should handle that by calling an unwrap_or_else or using a match statement (for more details on error handling check out this article). Like before this would effectively create an array type and drop the vector type.

💡Do not forget to specify the array length in the type conversion

let vec = vec![1, 2, 3];
// 3 is the array length , while i32 is the type 
// try_into needs this type declaration to be able to parse properly
let arr: [i32; 3] = vec.try_into().unwrap(); // Panics if sizes differ

So, when do you use arrays or Vectors

You should use arrays when :

  • You need a fixed-size collection (e.g., coordinates [x, y, z]).

  • Stack memory is preferred for performance (small datasets).

  • Compile-time size guarantees are required.

And use Vectors when:

  • The size is unknown at compile time (e.g., user input).

  • You need dynamic resizing (e.g., building a list incrementally).

  • You want access to rich methods (e.g., sorting, filtering).

Use arrays for static read-only operations and use vectors for anything else

What are the Performance Costs and Considerations around them?

  • Arrays: Faster for small, fixed-size data due to stack allocation and no heap overhead.

  • Vectors: Slightly slower due to heap allocation, but more flexible. Pre-allocate capacity to minimize reallocation:

Rust's Zero Cost Abstraction approach would save you some performance losses when using vectors but nothing beats the algorithm.

In other to save yourself some extra performance cost, if you can, specify the vector capacity.

The reason this works is because: If we know the vector capacity, the vector init Array size is pre-set removing that performance overhead that comes with inserts in a vector.

let mut vec = Vec::with_capacity(100);

💡If you know the expected Vector capacity, you can always set it to increase performance

In Conclusion

Array and Vectors are almost the same concepts but serve slightly different purposes. Start to see them like: Static Arrays and Dynamic Arrays.

If you are in a scenario where requiring fixed-size, stack-allocated data with minimal overhead is necessary then you should use Arrays, else you can use vectors as it would be much better when providing dynamic resizing and heap flexibility for unpredictable or growing Lists.

If you have a question feel free to reach out to me on LinkedIn.

Also, check out this course on backend engineering in Rust, which should help you master Rust from basics to advanced.

Course image
Become a Rust Backend Engineeer today

All-in-one Rust course for learning backend engineering with Rust. This comprehensive course is designed for Rust developers seeking proficiency in Rust.

Start Learning Now

Whenever you're ready

There are 4 ways we can help you become a great backend engineer:

The MB Platform

Join 1000+ backend engineers learning backend engineering. Build real-world backend projects, learn from expert-vetted courses and roadmaps, track your learnings and set schedules, and solve backend engineering tasks, exercises, and challenges.

The MB Academy

The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

Join Backend Weekly

If you like post like this, you will absolutely enjoy our exclusive weekly newsletter, Sharing exclusive backend engineering resources to help you become a great Backend Engineer.

Get Backend Jobs

Find over 2,000+ Tailored International Remote Backend Jobs or Reach 50,000+ backend engineers on the #1 Backend Engineering Job Board

Backend Tips, Every week

Backend Tips, Every week