# Vec, HashMap and String — Rust

Source: https://www.skillbyai.com/en/rust/c-coll

> The everyday collections.

## Growable, keyed, UTF-8

`Vec<T>` is a growable array; sort with `sort_by` and closures. `HashMap<K, V>` maps keys to values; the **entry API** (`entry(k).or_insert(0)`) inserts or updates without double lookups. `String` is an owned, growable, **UTF-8** string: `len()` counts bytes, not characters, so text in scripts like Devanagari has more bytes than characters. HashMap iteration order is unspecified, so sort when order matters.

## Expressive data processing

Vec, HashMap and String cover most needs; iterator chains process them clearly and efficiently.

![Three ideas: collections, iterators and closures, strings and slices.](assets/figures/rust/section-6-map.svg) — Figure 6.1 — Collections, iterators and slices.

## Sorting a Vec, counting words, UTF-8 strings, run

I ran this with Rust 1.99.0 (cargo run, edition 2024, standard library only). The cart is sorted by quantity; the entry API counts words (sorted by count then word for stable output); the string with Hindi text is 25 bytes but 13 characters.

```rust
use std::collections::HashMap;

fn main() {
    let mut cart: Vec<(&str, u32)> = vec![("pen", 2), ("ink", 1)];
    cart.push(("notebook", 3));
    cart.sort_by(|a, b| b.1.cmp(&a.1));
    println!("{cart:?}");

    let text = "the cat saw the dog and the cat ran";
    let mut counts: HashMap<&str, usize> = HashMap::new();
    for word in text.split_whitespace() {
        *counts.entry(word).or_insert(0) += 1;    // entry API: insert or update
    }
    let mut top: Vec<_> = counts.into_iter().collect();
    top.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(b.0)));
    println!("{:?}", &top[..3]);

    let mut s = String::from("Hello");
    s.push_str(", नमस्ते");
    println!("{s} | bytes={} chars={}", s.len(), s.chars().count());
}
```

Output:

```
[("notebook", 3), ("pen", 2), ("ink", 1)]
[("the", 3), ("cat", 2), ("and", 1)]
Hello, नमस्ते | bytes=25 chars=13
```

## Use the entry API

entry().or_insert() and and_modify() make insert-or-update code shorter and faster.

**Quiz:** What does String::len() return for non-ASCII text?

- [ ] The number of words
- [ ] The number of characters
- [x] The number of bytes, which can exceed the number of characters
- [ ] Always zero

*Answer:* The number of bytes, which can exceed the number of characters. Strings are UTF-8 bytes.
