Zbiory (ang. sets) to bardzo przydatna alternatywa dla listy. Są dużo bardziej wydajne, ale nie mogą zawierać duplikatów. Zbiory są bardzo przydatne, gdy potrzebujesz struktury danych, która powinna zawierać unikatowe pojęcia. Np. zbiór krajów, zbiór miast, itd. Najpopularniejszą implementacją interfejsu Set jest HashSet, i to tą klasę tutaj omówię.
Podobieństwa HashSet do listy
Metody tej klasy są bardzo podobne jak w przypadku klasy ArrayList. Dzieje się tak dlatego, bo oba interfejsy List i Set dziedziczą po interfejsie Collection. Najpierw stworzę przykładowy zbiór i wypełnię go danymi
Set<String> europeanCountries = new HashSet<>(); europeanCountries.add("Polska"); europeanCountries.add("Niemcy"); europeanCountries.add("Francja"); europeanCountries.add("Niemcy"); for(String country: europeanCountries) { System.out.println(item); }
Większość metod jest, jak widzisz, podobnych do tych z list. Skupię się, więc na tych, które są ciekawe i je jeszcze nie omówiłem:
Set<String> asianCountries = new HashSet<>(); asianCountries.add("Japonia"); asianCountries.add("Wietnam"); asianCountries.add("Indie"); Set<String> allWorld = new HashSet<>(); allWorld.addAll(europeanCountries); allWorld.addAll(asianCountries);
Stworzyłem tutaj drugi zbiór i za pomocą addAll dodałem do nowej kolekcji dwie obecnie istniejące.
W podobny sposób mogę stosować też instrukcję warunkową oraz usuwanie:
if (allWorld.containsAll(europeanCountries)) { allWorld.removeAll(europeanCountries); }
Z allWorld zostały usunięte wszystkie kraje, które należały do kontynentu Azjatyckiego.
Ostatnią ciekawą metodą jest retainAll, która pozostawia w kolekcji wybrane rekordy:
allWorld.add("USA"); allWorld.retainAll(europeanCountries);
USA zostaną usunięte z allWorld, ponieważ nie zawierają się wśród zbioru państw Europejskich.
Zbiór a hashcode i equals
Na koniec pamiętaj, że HashSet zadziała właściwie, jeśli klasa użyta w nim, ma poprawnie napisane metody hashcode i equals (tak jak np. String).* Nigdy nie bazuj na domyślnych implementacjach, zapewnionych przez niejawne dziedziczenie po klasie Object. Nie daje Ci to pewności, że metody te będą optymalnie wyliczały hash i zapobiegały kolizji.
*Zobacz poprzednią lekcję o klasie HashMap.
Link do lekcji: https://github.com/developeronthego/java-middle/tree/master/src/main/java/middle/lesson16