accounts.insert(account, account_info);
try_logon(&accounts, "j.everyman", "psasword123");
try_logon(&accounts, "j.everyman", "password123");
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Рассмотрим 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>>());
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
(Пример адаптирован из документации)
Когда необходимо множественное владение, может использоваться Rc (счётчик ссылок). Rc отслеживает количество ссылок, означающих количество владельцев значения, сохранённого в Rc.
Количество ссылок на Rc увеличивается на 1 каждый раз, когда Rc клонируется, и уменьшается на 1, когда один из клонов выходит из области видимости и удаляется. Когда количество ссылок на Rc становится равным нулю, т.е. владельцев больше нет, и Rc, и значение удаляются.
При клонировании Rc никогда не делается глубокая копия. Клонирование лишь создаёт другой указатель на обёрнутое значение и увеличивает счётчик.
use std::rc::Rc;
fn main() {
let rc_examples = "Пример с Rc".to_string();
{
println!("--- Создана rc_a ---");
let rc_a: Rc<String> = Rc::new(rc_examples);
println!("Количество ссылок на rc_a: {}", Rc::strong_count(&rc_a));
{
println!("--- rc_a клонировано в rc_b ---");