> For the complete documentation index, see [llms.txt](https://jmkoni.gitbook.io/rust/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jmkoni.gitbook.io/rust/common-concepts/collections.md).

# Collections

### Strings

In Rust, Strings are implemented as a collection of bytes. There are effectively two string types: `str`, which is in the core language and commonly referred to as a *string slice*, and `String`, which is provided by Rust's standard library. Here are various ways to initialize a string:

```rust
let mut s = String::new(); // initializes an empty String
let data = "initial contents"; // is a string slice
let s = data.to_string(); // assign it to s, but first make it a String

let hi = "hi".to_string(); // or you could do this
let bye = String::from("bye"); // or this!
```

A `String` can grow in size and the contents can change. Let's look at some code that covers a variety of ways to alter a `String`:

{% code title="main.rs" %}

```rust
fn main() {
  let mut foo = String::from("foo");
  let bar = "bar";
  foo.push_str(&bar);
  println!("foo is {}", foo);
  println!("bar is {}", bar);
  
  let mut lol = String::from("lo");
  lol.push('l');
  println!("lol is {}", lol);
  
  let hello = String::from("Hello, ");
  let world = String::from("world!");
  let hello_world = hello + &world; // Note that hello has been moved here and can no longer be used
  println!("hello_world is {}", hello_world);
  
  let tic = String::from("tic");
  let tac = String::from("tac");
  let toe = String::from("toe");
  // this code is unweildy and it also moves `tic`.
  // if you want to see what the error looks like,
  // uncomment out line 23
  // let game = tic + "-" + &tac + "-" + &toe; 
  let game = format!("{}-{}-{}", tic, tac, toe);
  println!("game is {}", game)
}
```

{% endcode %}

The output of this should look like:

```
foo is foobar
bar is bar
lol is lol
hello_world is Hello, world!
game is tic-tac-toe
```

We can also iterate over a string using a `for` loop:

{% code title="main.rs" %}

```rust
fn main() {
  for c in "hi y'all".chars() {
      println!("{}", c);
  }
}
```

{% endcode %}

### Hash Maps

A hash map is a collection of key-value pairs. The type `HashMap<K, V>` stores a mapping of keys of type `K` to values of type `V`. Here's an example that creates a `HashMap` and retrieves values:

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

fn main() {

  let mut scores = HashMap::new();

  scores.insert(String::from("Blue"), 10);
  scores.insert(String::from("Yellow"), 50);
  let score = get_score(scores, String::from("Red"));
  //let score = get_score(scores, String::from("Blue"));
}

fn get_score(scores: HashMap<String, i64>, team_name: String) -> String {
  let score = match scores.get(&team_name) {
                Some(num) => num.to_string(),
                None => "nonexistent".to_string()
              };
  println!("{}'s score is {}", team_name, score);
  score
}
```

`get` will return an [`option`](https://doc.rust-lang.org/std/option/) type. To get the value out of the `option` (which has both `Some<V>` a `None`), we have to use pattern matching again. Since `None` doesn't have a value, I want to return the string "nonexistent" if the team isn't in the `HashMap`.

{% hint style="info" %}
Why is `let score = get_score(scores, String::from("Blue"));` commented out? When we use `scores` in line 9, that makes the contents of `scores` owned by `get_scores` and you can no longer reference it. I'll be explaining a bit more about that in [Ownership](/rust/ownership.md).
{% endhint %}
