ハッシュ集合

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

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

A HashSet's unique feature is that it is guaranteed to not have duplicate elements. That's the contract that any set collection fulfills. HashSet is just one implementation. (see also: BTreeSet)

If you insert a value that is already present in the HashSet, (i.e. the new value is equal to the existing and they both have the same hash), then the new value will replace the old.

This is great for when you never want more than one of something, or when you want to know if you've already got something.

But sets can do more than that.

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

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

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

  • intersection:両方の集合にある値のみを取得。

  • symmetric_difference: get all the elements that are in one set or the other, but not both.

以下の例でこれらをすべて見ていきましょう。

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>>());
}

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