Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

해시셋

HashSet을 키에만 관심이 있는 HashMap이라고 생각해보세요 (HashSet<T>는 실제로 HashMap<T, ()>의 래퍼(wrapper)일 뿐입니다).

“그게 무슨 소용이죠?“라고 물으실 수 있습니다. “그냥 키를 Vec에 저장할 수도 있잖아요.”

HashSet의 고유한 특징은 중복된 요소가 없음을 보장한다는 것입니다. 이는 모든 집합(set) 컬렉션이 지키는 계약입니다. HashSet은 그 중 하나의 구현일 뿐입니다. (참고: BTreeSet)

이미 HashSet에 존재하는 값을 삽입하면 (즉, 새 값이 기존 값과 같고 해시도 같다면), 새 값이 기존 값을 대체하게 됩니다.

이는 무언가를 중복 없이 유지하고 싶을 때나, 이미 가지고 있는지 알고 싶을 때 매우 유용합니다.

하지만 집합은 그 이상의 일을 할 수 있습니다.

집합은 4가지 주요 연산을 가집니다 (다음 호출들은 모두 이터레이터를 반환합니다):

  • union(합집합): 두 집합에 있는 모든 고유한 요소들을 가져옵니다.

  • difference(차집합): 첫 번째 집합에는 있지만 두 번째 집합에는 없는 모든 요소들을 가져옵니다.

  • intersection(교집합): 오직 양쪽 집합 모두에 있는 모든 요소들을 가져옵니다.

  • symmetric_difference(대칭차집합): 한쪽 집합에는 있지만 _양쪽 모두_에 있지는 않은 모든 요소들을 가져옵니다.

다음 예제에서 이들 모두를 시도해 보세요:

use std::collections::HashSet;

fn main() {
    let mut a: HashSet<i32> = vec![1i32, 2, 3].into_iter().collect();
    let mut b: HashSet<i32> = vec![2i32, 3, 4].into_iter().collect();

    assert!(a.insert(4));
    assert!(a.contains(&4));

    // `HashSet::insert()`는 값이 이미 존재하면 false를 반환합니다.
    assert!(b.insert(4), "값 4는 이미 집합 B에 있습니다!");
    // FIXME ^ 이 줄을 주석 처리하세요

    b.insert(5);

    // 컬렉션의 요소 타입이 `Debug`를 구현한다면,
// 컬렉션도 `Debug`를 구현합니다.
// 보통 `[elem1, elem2, ...]` 형식으로 요소를 출력합니다.
    println!("A: {:?}", a);
    println!("B: {:?}", b);

    // [1, 2, 3, 4, 5]를 임의의 순서로 출력합니다
    println!("합집합: {:?}", a.union(&b).collect::<Vec<&i32>>());

    // 이는 [1]을 출력해야 합니다
    println!("차집합: {:?}", a.difference(&b).collect::<Vec<&i32>>());

    // [2, 3, 4]를 임의의 순서로 출력합니다.
    println!("교집합: {:?}", a.intersection(&b).collect::<Vec<&i32>>());

    // [1, 5]를 출력합니다
    println!("대칭차집합: {:?}",
             a.symmetric_difference(&b).collect::<Vec<&i32>>());
}

(예제는 문서에서 발췌 및 수정되었습니다.)