# Collections

# Arrays

Arrays are placed on the stack, since their size is static and always needs to be predefined.

let countries = ["Poland", "Brazil"];

Iterator is returned with countries.iter();.

for country in countries.iter() {


Array is typed like this: [u32, 5] - 5 elements of type u32. Each array with different type and size is like a separate type in Rust.

# Vectors

Another collection type. It's dynamic, so it's placed on the heap (it's a struct). Vec<T> is like a List<T> in C#. They are more expensive than arrays. Elements are placed next to each other in memory.

Creating vectors:

let v: Vec<i32> = Vec::new(); //empty
let v = vec![1, 2, 3]; // infers type, uses a macro

Operations on vectors:

let mut v = Vec::new(); // no type needed, it's infered from the code below

// update

// read
let third: &i32 = &v[2];

match v.get(2) {
  Some(third) => println!("The third element is {}", third),
  None => println!("There is no third element."),
} // returns Option<&T>

The second way of reading will not panic if we try to access element out of index. It will return Option.None instead.

# HashMaps

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

let team_name = String::from("Blue");
let score = scores.get(&team_name); // returns Option<&T>
scores.entry(String::from("Yellow")).or_insert(60); // inserts only if Yellow key is not there yet

# Iterators

Iterators give access to consecutive elements in collections. Iterators implement the Iterator trait, which exposes next() method and Item. It's easy to define our own iterators. Iterators provide zero-cost abstractions, they are very performant.

There are three methods on collections that return iterators:

  • iter() - iterates over immutable references to items in the collection
  • iter_mut() - iterates over mutable references to items in the collection
  • into_iter() - returns owned values from the collection

# Consuming Adaptors

Some methods defined on the Iterator trait take ownership of the iterator and return something useful. An example is the sum() method.

# Collect function

The collect() function consumes iterator into an actual collection of values.

let args: Vec<String> = env::args().collect();

# Iterator Adaptors

Some other methods can transform an iterator into another kind of iterator. These iterators are lazy, so to actually do anything the resulting iterator needs to be consumed.


  • map() - takes a closure to be executed agains each item and returns closure's result. It's similar to JS's map in concept.
  • filter() - returns an iterator that filters source collection based on a closure returning bool.
  • skip() - skips some items.


collect() applied on top of iterator adaptor returns a new collection of values.

Last Updated: 1/15/2023, 6:32:34 PM