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>>()); }
(Пример адаптирован из документации)