HashSet

Рассмотрим HashSet как HashMap в котором мы заботимся только о ключах (в действительности, HashSet<T> - это просто адаптер к HashMap<T, ()>).

"Какой в этом смысл?", - спросите вы. - "Я бы мог просто хранить ключи в Vec."

Уникальная особенность HashSet в том, что он гарантирует, что в нём не содержится повторяющихся элементом. Это условие выполняет любой набор (set). HashSet - всего лишь одна реализация (смотрите также: BTreeSet).

Если вы вставите значение, которое уже содержится в HashSet, (например, новое значение равно существующему значению и они оба имеют одинаковый хэш), то новое значение заменит старое.

Это хорошо подходит для случаев, когда вы не хотите иметь в коллекции больше одного "чего-либо" или когда вам необходимо знать имеете ли вы что-либо.

Но наборы могут делать гораздо более.

Наборы имеют 4 основные операции (все вызовы вернут итератор):

  • union: получить все уникальные элементы из обоих наборов.

  • difference: получить все элементы, представленные в первом наборе, но отсутствующие во втором.

  • intersection: получить только те элементы, которые присутствуют в обоих наборах.

  • symmetric_difference: получить элементы содержащиеся либо только в первом наборе, либо только во втором, но не в обоих (xor).

Попробуем эти методы в следующем примере:

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!");
    // ИСПРАВЬТЕ ^ Закомментируйте эту строку

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

(Пример адаптирован из документации)