## 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

# ハッシュ集合

値がなく、キーだけの`HashMap`を想像してみてください。これはハッシュ集合（`HashSet`）と呼ばれるものです。（`HashSet<T>`は、実際には`HashMap<T, ()>`のラッパーです。）

「何の意味があるの？フツーにキーを`Vec`に入れればいいじゃん」そう思いましたね？

それは、`HashSet`独自の機能として、要素に重複がないということが保証されるためです。これは全ての集合型がもつ機能です。`HashSet`はその実装の1つであり、他には`BTreeSet`等があります。

`HashSet`に、すでに存在する値を加えようとすると、（すなわち、加えようとしている値のハッシュ値と、要素中のいずれかの値のハッシュ値が等しい場合、）新しい値によって古い値が上書きされます。

これは、同じ値を2つ以上欲しくない場合や、すでにある値を持っているか知りたい場合にとても有効です。

しかし、集合型の機能はそれだけではありません。

集合型には4つの主要なメソッドがあり、（すべてイテレータを返します。）

- `union`：2つの集合型のどちらか一方にある値を全て取得。

- `difference`：1つ目の集合にあり、かつ2つ目には存在しない値を全て取得。

- `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), "Value 4 is already in set B!");
        // FIXME ^ この行をコメントアウトしましょう

        b.insert(5);

        // 集合の要素が、`Debug`を実装している型の場合、
        // 集合そのものも`Debug`を実装します。
        // 通常は`[elem1, elem2, ...]`のように要素を出力します。
        println!("A: {:?}", a);
        println!("B: {:?}", b);

        // [1, 2, 3, 4, 5]を順不同に出力。
        println!("Union: {:?}", a.union(&b).collect::<Vec<&i32>>());

        // これは[1]を出力。
        println!("Difference: {:?}", a.difference(&b).collect::<Vec<&i32>>());

        // [2, 3, 4]を順不同に出力。
        println!("Intersection: {:?}", a.intersection(&b).collect::<Vec<&i32>>());

        // [1, 5]を出力。
        println!("Symmetric Difference: {:?}",
                 a.symmetric_difference(&b).collect::<Vec<&i32>>());
    }

例は公式ドキュメントから持ってきています。