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, ()> の単なるラッパーです)。

「それに何の意味があるのですか?」とあなたは尋ねるでしょう。「キーを Vec に格納するだけでもよいはずです。」

HashSet の独自の特徴は、 重複する要素を持たないことが保証されている点です。 これは、どの set コレクションも満たす契約です。 HashSet は実装の 1 つにすぎません。(こちらも参照: BTreeSet

HashSet にすでに存在する値を挿入すると、 (つまり、新しい値が既存の値と等しく、両方が同じハッシュを持つ場合) 新しい値が古い値を置き換えます。

これは、あるものを 2 つ以上持ちたくない場合や、 すでに持っているかどうかを知りたい場合に非常に便利です。

しかし、set にはそれ以上のことができます。

set には 4 つの主要な操作があります(以下の呼び出しはすべてイテレーターを返します)。

  • union: 両方の set に含まれる一意な要素をすべて取得します。

  • difference: 最初の set には含まれるが、2 番目の set には含まれない要素をすべて取得します。

  • intersection: _両方_の set にのみ含まれる要素をすべて取得します。

  • symmetric_difference: どちらか一方の set には含まれるが、_両方_には含まれない要素をすべて取得します。

次の例で、これらをすべて試してみましょう。

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

(例はドキュメントから改変されています。)