Interfejs Set - Zbiory

Set jest interfejsem wchodzącym w skład Collections Framework Javy. Reprezentuje on kolekcję unikalnych elementów, ale nie wspomina nic o kolejności ich przechowywania, ponieważ ta zależy już od konkretnej jego implementacji. Set jest typem generycznym, co oznacza, że możemy określić elementy jakiego typu będziemy w nim przechowywali, a to pozwoli nam uniknąć konieczności rzutowania.

Implementacje

java set hashset treeset linkedhashset

Wśród dostępnych implementacji zbiorów możemy wyróżnić ich trzy rodzaje:

  • HashSet - podstawowa implementacja, zapewnia unikalność elementów, ale nie mamy żadnej gwarancji co do ich kolejności. Wewnętrznie wykorzystywana jest tablica mieszająca, co wymaga poprawnej implementacji metod hashCode() oraz equals().
  • TreeSet - implementacja oparta o drzewa czerwono czarne, która oprócz unikalności elementów gwarantuje nam uporządkowanie wstawianych elementów zgodnie z naturalnym porządkiem. Porządek ten wyznaczany jest poprzez implementację interfejsu Comparable lub zastosowanie odpowiedniego Comparatora.
  • LinkedHashSet - implementacja wykorzystująca wewnętrznie zarówno tablicę mieszającą jak i dodatkową listę podwójnie wiązaną, dzięki czemu oprócz unikalności elementów zagwarantowana jest także kolejność elementów zgodna z tą w jakiej były one dodawane

Kurs Java

Różnica między HashSet, TreeSet i LinkedHashSet

HashSet jest podstawową implementacją, która zapewnia jedynie unikalność elementów, TreeSet gwarantuje dodatkowe sortowanie, a LinkedHashSet pamięta dodatkowo kolejnoś wstawiania.

Wybór odpowiedniej implementacji zależy przede wszystkim od naszych potrzeb. Wszystkie zbiory są strukturami wydajnymi, ponieważ opierają się albo o tablice mieszające lub struktury drzewiaste, a to zapewnia stałą lub logarytmiczną złożoność obliczeniową.

Dostępne metody

Najważniejsze metody w interfejsie Set to odziedziczone z interfejsu Collection:

  • boolean add(E e) - dodaje unikalny element do zbioru, w przypadku, gdy element się powtarza dodawanie jest ignorowane. Unikalność jest sprawdzana na podstawie metod hashCode() i equals(). Do zbioru można dodać jedną wartość null
  • boolean contains(Object o) - sprawdza, czy obiekt 'o' znajduje się w zbiorze
  • boolean isEmpty() - sprawdza, czy zbiór jest pusty
  • Iterator iterator() - zwraca iterator. Kolejność elementów jest zależna od tego z jakiej implementacji korzystamy
  • boolean remove(Object o) - usuwa element 'o' ze zbioru
  • int size() - zwraca rozmiar (ilość elementów) zbioru

Dodatkowo w poszczególnych implementacjach znajdziemy dodatkowe metody, przykładowo w TreeSet znajdziemy metodę first() , która zwraca "najmniejszy" obiekt w rozumieniu naturalnego porządku, oraz last() , która zwraca największy z nich. Więcej znajdziesz w dokumentacji.

Przykład

Jako przykład napiszmy program, w którym stworzymy zbiór typu TreeSet (posortowany) z imionami. Spróbujmy dodać kilka duplikatów, a następnie wyświetlmy wynik działania kilku metod.

import java.util.Set;
 import java.util.TreeSet;
 
 public class SetExample {
 	public static void main(String[] args) {
 		Set<String> names = new TreeSet<>();
 		names.add("Kasia");
 		names.add("Ania");
 		names.add("Ania");
 		names.add("Wojtek");
 		names.add("Zuza");
 		names.add("Zuza");
 		
 		int setSize = names.size();
 		System.out.println("Number of names: " + setSize);
 		boolean isThereAnia = names.contains("Ania");
 		System.out.println("Is Ania in this set? " + isThereAnia);
 		for(String name: names) {
 			System.out.println(name);
 		}
 	}
 }

Stworzyliśmy zbiór typu TreeSet i przypisaliśmy go do zmiennej typu Set. W przypadku wszystkich rodzajów kolekcji dobrze jest się posługiwać referencją ogólnego typu, ponieważ możemy w takiej sytuacji podmienić TreeSet np. na LinkedHashSet w dowolnym momencie, bez konieczności zmiany reszty kodu, jest to oczywiście zasługa polimorfizmu.

Do zbioru próbujemy dodać kilka imion w tym duplikaty Ani oraz Zuzy. Ponieważ zbiór oczekuje elementów unikalnych, to wystąpią one tylko raz. Dodatkowo przy wyświetlaniu zauważymy, że elementy są posortowane, ponieważ klasa String implementuje interfejs Comparable.

set konsola

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.