해시맵
모두에게 익숙한 그 해시맵 타입을 알아보기로 함. HashMap<K, V>(이하 해시맵) 은 std 라이브러리에서 제공하지만, 벡터만큼 사용 빈도가 높다고 여겨지진 않았는지 자동으로 로드되지 않음. use 를 사용해야 함. 해시맵은 제너릭 타입이 적용되며, 요소의 키와 값이 각각 같아야 함.
해시맵 생성
기본적으로 아래와 같이 생성하고 데이터를 넣음.
collect 메서드를 사용하면 두 벡터를 이용해서 맵으로 합칠 수 있음.
teams 의 요소는 키로, initial_scores 의 요소는 값으로 1:1 매핑된 해시맵이 생성됨.
타입을 '<_, _>' 으로 지정했는데, 이는 collect 메서드는 다양한 타입의 맵을 리턴할 수 있고, 호출 결과로 어떤 타입이 올지 모르기 때문. '_' 를 사용하면 러스트는 벡터 안의 데이터 타입을 기반으로 해시맵의 타입을 추론할 수 있음.
해시맵과 오너십
해시맵의 키/값 insert 에도 오너십 규칙이 적용됨.
변수 key, value 는 오너십을 상실함.
어떤 값의 레퍼런스(참조)를 해시맵에 넣는다면, 그 값은 해시맵으로 이동하지 않음. 레퍼런스가 가리키는 값은 해시맵이 유효한 이상 반드시 유효해야 함. 이는 라이프타임에 관한 것인데, 후에 자세히 다룸.
해시맵 값 접근
아래와 같이 get 메서드를 이용해서 해시맵에 저장된 값에 접근할 수 있음.
get 메서드는 Option<&V> 를 리턴함. 위의 변수 blue 는 Some(&String::from("color")) 가 됨. 만약 키에 해당하는 값이 없으면 get 메서드는 None 을 리턴함.
아래의 방법으로 맵을 순회하며 키와 값을 얻을 수 있음.
해시맵 값 변경
해시맵은 하나의 키로 하나의 값만 할당할 수 있음. 만약 맵에 넣으려는 키에 해당하는 값이 이미 존재할 경우, 새로운 값으로 덮어쓸 것인지 기존 값을 유지할 것인지 결정해야 함.
값 덮어쓰기
아래와 같이 이미 존재하는 키로 값을 넣으면 그냥 새로운 값으로 덮어쓰고 기존 값은 사라짐.
값 유지하기
해시맵에 entry 메서드가 있음. 파라미터로 키 값을 받아서, 이 키에 해당하는 값이 이미 있는지 체크하고 그 결과를 리턴함. 리턴 타입은 enum 타입 Entry 임. 아래와 같이 사용.
Entry 타입의 메서드 or_insert 는 Entry 의 값이 있을 경우 그 값을 리턴하고, 값이 없을 경우 파라미터로 주어진 값을 맵에 넣음. 위의 코드에서는 키 Yellow 는 값이 없으니 50 을 값으로 넣고, 키 Blue 는 값이 있으니 기존 값 10을 유지함.
기존 값을 기반으로 값 변경하기
기존 값을 그대로 덮어쓰거나 유지하지 않고, 기존 값을 이용해서 새로운 값을 만드는 경우도 있음.
위 코드의 아웃풋은 다음과 같음.
{"wonderful": 1, "world": 2, "hello": 1}
코드의 수행 과정을 다음과 같음.
1. for word in text.split_whitespace() {..} 는 text 의 문자열을 공백 기준으로 잘라낸 결과를 가지고 순회.
2. let count = map.entry(word).or_insert(0); 는 map 에 해당 단어가 키로 존재하는지 체크(entry)하여 or_inert(0) 호출, 즉 값이 이미 있다면 있는 값을 리턴하고, 없다면 0 을 값으로 맵에 넣음.
3. *count += 1; 은 존재하는 값에 1 을 더함.
결국 이미 키가 존재하는 경우 count 를 1 더하고, 없으면 0 으로 초기화 함. or_insert 메서드는 값이 있는 경우 뮤터블 레퍼런스(*mut V) 를 리턴하기 때문에, 역참조(*) 로 값을 변경할 수 있음.
해싱 함수
기본적으로 러스트의 해시맵은 서비스 거부 공격(Denial of Service)을 방어할 수 있는, 암호화된 보안 해싱 함수를 사용함. 이 함수는 가장 빠른 해싱 함수는 아님. 성능을 어느 정도 희생하여 안정성을 취한 형태. 만약 다른 해싱 함수를 사용하길 원한다면, hasher 를 명시하여 원하는 해싱 함수를 지정할 수 있음. 이에 대한 자세한 내용은 나중에 다루기로 함.
'Rust' 카테고리의 다른 글
에러 핸들링(Result) (0) | 2018.02.26 |
---|---|
에러 핸들링(panic) (0) | 2018.02.26 |
컬렉션(스트링) (0) | 2018.02.24 |
컬렉션(벡터) (0) | 2018.02.24 |
모듈(다른 모듈 접근) (0) | 2018.02.22 |