Set — to nieuporządkowana kolekcja unikalnych elementów, zaimplementowana jako tabela haszująca. Główna różnica w porównaniu do Array — brak wartości duplikujących oraz brak porządku. Główne interfejsy: metody wstawiania (insert), usuwania (remove), sprawdzania obecności (contains).
Czas wykonania:
insert, remove i contains działają średnio w czasie O(1).Przykład użycia:
var numbers: Set<Int> = [1, 2, 3] numbers.insert(4) // Set: 1, 2, 3, 4 numbers.insert(2) // Set się nie zmieni, 2 już jest obecne numbers.remove(1) // Set: 2, 3, 4 print(numbers.contains(3)) // true
Używaj Set, gdy ważna jest unikalność, ale nie ważna jest kolejność. Porównaj z Array:
Array odbywa się w czasie O(n).Array dozwolone są takie same wartości.Zbiór wspiera: ∪, ∩, −, ⊆, ⊇ i inne operacje teorii zbiorów.
Pytanie:
Czy poniższy kod skompiluje się i dlaczego?
let set: Set = [[1, 2], [3, 4]]
Odpowiedź:
Nie, nie skompiluje się. Set wymaga, aby typ elementów spełniał protokół Hashable. Tablica (Array) nie implementuje Hashable, dlatego nie można utworzyć zbiorów tablic bezpośrednio. Na przykład, Set<Int> jest poprawny, a Set<[Int]> — nie.
Historia
W jednym z serwisów programiści przechowywali unikalne identyfikatory obiektów jako [Int], a nie Set<Int>. Powodowało to problemy: sprawdzanie obecności i usuwanie działało wolno (czas — O(n)), pojawiały się duplikaty, naruszała się logika biznesowa.
Historia
Próba umieszczenia w Set nietypowych typów (na przykład tworzono Set<MyModel>), ale typ nie wprowadzał Hashable. Kod kompilował się dopiero po dodaniu odpowiednich protokołów, ale przy realizacji błędów w hash(into:) pojawiały się kolizje i nieprzewidywalne zachowanie podczas działania.
Historia
Programista spodziewał się, że kolejność przeglądania elementów w Set będzie zgodna z kolejnością wstawiania, i budował UI w tej samej kolejności. W rezultacie przy każdym uruchomieniu kolejność była inna, co prowadziło do niespójnego wyświetlania danych u końcowego użytkownika.