1. HashMap

  • 매핑은 해쉬 함수(hashing function)을 통해 동작한다.
  • 해쉬 함수는 키와 값을 메모리 어디에 저장할지 결정한다.

2. 생성하기

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
  • HashMap을 use로 가져와서 사용해야 한다.
  • 세가지 컬렉션(Vector, String, Hashmap) 중 HashMap의 사용빈도가 적기 때문에 Prelude 내에 자동으로 가져오는 기능에 포함되어있지 않다.
  • Vector와 마찬가지로 해쉬맵은 데이터를 힙에 저장한다.
  • HashMap은 String 타입의 키와 i32 타입을 갖는다.
  • 모든 키는 같은 타입이어야 한다.
  • 모든 값은 같은 타입이어야 한다.

3. 두 벡터를 묶어 해쉬맵으로 만들기

use std::collections::HashMap;

let teams = vec![String::from("Blue"), String::from("Yellow")];
let initial_scores = vec![10, 50];
let scores: HashMap<_,_> = teams.iter().zip(initial_scores.iter()).collect();
  • 밑줄로 된 타입은, 벡터에 담긴 데이터의 타입을 통해 추론된다.

4. 해쉬맵과 소유권

use std::collections::HashMap;

let field_name = String::from("Favorite color");
let field_value = String::from("Blue");
let mut map = HashMap::new();
map.insert(field_name, field_value);
// 여기서 부터 field_name, field_value는 유요하지 않음.
println!("{}:{}", field_name, field_value); // 에러
  • i32 와 같이 Copy 트레잇이 구현된 타입은 해쉬맵 안으로 복사된다.
  • String 같은 소유값에 대해서는 해쉬맵으로 소유권이 이동된다.

5. 값 사용하기

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);
// 결과값은 Some(&10) 이다.
  • 해쉬맵의 get 메소드는 Option<&V>를 반환한다.

6. 반복 사용

for (key, value) in &scores {
    println!("{}: {}", key, value);
}

7. 값 덮어쓰기

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Blue"), 25);
println!("{:?}", scores);
// 결과: {"Blue": 25}
  • 똑같은 키에 다른 값을 삽입하면 덮어쓴다.

8. 값이 없는 경우만 삽입

scores.insert(String::from("Blue"), 10);
scores.entry(String::from("Yellow")).or_insert(50);
scores.entry(String::from("Blue")).or_insert(50);
// 결과: {"Yellow": 50, "Blue": 10}
  • entry 함수의 리턴값은 열거형 Entry다.
  • Entry는 해당 키가 있는지 없는지는 알려줌.
  • Entry.or_insert 메소드는 키가 존재하는 경우: Entry 키에 대한 값을 반환한다.
  • Entry.or_insert 메소드는 키가 없는 경우: 파라미터로 주어진 값을 삽입하고 반환한다.

9. or_insert() -> &mut V

let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}
println!("{:?}", map);
// 결과: {"world": 2, "hello": 1, "wonderful": 1}
  • on_insert 메소드는 해당 키에 대한 값의 가변 참조자 (&mut V)를 반환한다.
  • *count: 역참조하여 키 값을 수정할 수 있다.

10. 해쉬 함수

  • HashMap은 기본적으로 Denial of Service(DoS) 공격에 저항하는 기능을 제공할 수 있는 암호학적으로 보안되는 해쉬 함수를 사용한다.
  • 가장 빠른 해쉬 알고리즘은 아니다.
  • 사용자는 다른 해쉬함수로 바꿀 수 있다.
  • 해쉬어(hasher): BuildHasher 트레잇이 구현된 타입.

11. 참고자료