EnumSet

Skoro rozpoczęliśmy temat typów wyliczeniowych to również warto powiedzieć o kolekcji EnumSet.

Znasz już  jedną kolekcję – jest to Lista – np. LinkedList lub ArrayList. Listy są po prostu zbiorem wszystkich wartości, które się dodaje – lecz, czym jest set?

Set

Zacznijmy od tego czym jest set – jest zbiorem tylko unikalnych obiektów!

Przypuśćmy, że mamy set (zbiór) studentów, gdzie każdy ma przypisany do siebie unikalny numer studenta – w takim zbiorze, więc nie ma miejsca na duplikację elementów – jeśli będzie próba dodania studenta o tym samym numerze to się on po prostu nie doda.

Jak działają porównania czy obiekty są takie same?

Oczywiście na początek wchodzi porównanie referencji czyli adresów np.:

Object s1 = new Object();
Object s2 = new Object();
if (s1 == s2);

Jeśli warunek zostanie spełniony to obiekty są porównywane metodą equals – czyli jest sprawdzana zawartość obiektu, według naszego wcześniej przedstawionego schematu. Wystarczy, że w metodzie equals będzie tylko sprawdzenie równości numeru studenta i nasz set będzie działał poprawnie.

EnumSet

Skoro wiesz teoretycznie czym jest kolekcja set to można przejść do EnumSet – a to po prostu zbiór na enumy.

Oczywiście enumy można przechowywać w zwykłych listach lub tablicach, ale pytanie po co? – skoro mamy do tego już stworzone kolekcje.

A może EnumList…

Skoro jest zwykła lista dla obiektów to może istnieje również lista na typów wyliczeniowych? W końcu co w sytuacji, gdy chcemy przechowywać duplikaty?

Ten case jest całkowicie bez sensu, w końcu założeniem typu wyliczeniowego jest unikalność – czyli bycie singletonem. W takim razie enum powinien być przechowywany np. w EnumSet zamiast w zwykłych listach, które spowodują duplikację elementów.

Jeszcze nie wyobrażasz sobie tego?

Lista wyboru

Przypuśćmy, że mamy w magazynie bluzę, która jest w kolorach RED, BLUE, GREEN – oczywiście kolory są trzymane w enum – jak przystało na dobrego programiste.

Trzymanie listy kolorów w zwykłej liście (choć mamy listę kolorów :P) jest złym pomysłem, ponieważ, może dojść do duplikacji kolorów i na interfejsie użytkownika (UI) zostaną wyświetlone te same kolory kilkukrotnie, a tego oczywiście nie chcemy.

Zaczynajmy!

Oczywiście skoro chcemy przechowywać enumy to trzeba je najpierw mieć – przywołajmy kolory z poprzedniej lekcji:

package pl.maniaq;

import java.awt.*;

public enum Colors implements ColorOperations{
    RED(255, 0, 0), GREEN(0, 255, 0), BLUE(0, 0, 255), YELLOW(255, 204, 0);

    private int red;
    private int green;
    private int blue;

    Colors(int red, int green, int blue) {
        this.red=red;
        this.green=green;
        this.blue=blue;
    }

    @Override
    public String getHexColor() {
        return "#"+Integer.toHexString(getRGB());
    }

    @Override
    public int getRGB() {
        return new Color(red, green, blue).getRGB();
    }

}

Gdy mamy już typ wyliczeniowy to możemy przejść do stworzenia kolekcji EnumSet – robi się to trochę w inny sposób niż normalnie – albowiem bez konstruktora tylko przez statyczną metodę. Podobnie, gdy robiliśmy singletony. 😉

EnumSet<Colors> colors = EnumSet.noneOf(Colors.class);

Metoda noneOf tworzy nam pustego enuma dla typ, który przekazujemy jako argument – w naszym przypadku jest to Colors.class.

Możemy również użyć metody allOf, który stworzy automatycznie zbiór wraz ze wszystkimi elementami danego enuma:

EnumSet<Colors> colors = EnumSet.allOf(Colors.class);

Choć my zostaniemy przy pustym zbiorze:

EnumSet<Colors> colors = EnumSet.noneOf(Colors.class);

I metodą add dodamy do niego dwa kolory:

colors.add(Colors.RED);
colors.add(Colors.BLUE);

Sprawdzimy czy w naszym zbiorze jest kolor niebieski metodą contains – czyli zawiera:

if (colors.contains(Colors.BLUE)) {
    System.out.println("Jest kolor niebieski!");
}

Usuniemy kolor czerwony metodą remove:

colors.remove(Colors.RED);

Sprawdzimy czy kolekcja nie jest pusta negacją rezultatu metody isEmpty:

if (!colors.isEmpty()) {
    System.out.println("Kolekcja nie jest pusta!");
}

Metodą size możemy jeszcze sprawdzić ilość elementów w kolekcji:

System.out.println("Ilość elementów: " + colors.size());

Oraz na koniec wyświetlimy zawartość zbioru:

System.out.println("Elementy: "  + colors.toString());

Po wszystkich operacjach nasz kod wygląda tak:

package pl.maniaq;


import java.util.EnumSet;

public class Main {

    public static void main(String[] args) {
        EnumSet<Colors> colors = EnumSet.noneOf(Colors.class);

        colors.add(Colors.RED);
        colors.add(Colors.BLUE);

        if (colors.contains(Colors.BLUE)) {
            System.out.println("Jest kolor niebieski!");
        }

        colors.remove(Colors.RED);

        if (!colors.isEmpty()) {
            System.out.println("Kolekcja nie jest pusta!");
        }

        System.out.println("Ilość elementów: " + colors.size());

        System.out.println("Elementy: "  + colors.toString());

    }
}

A po uruchomieniu otrzymujemy:

Jest kolor niebieski!
Kolekcja nie jest pusta!
Ilość elementów: 1
Elementy: [BLUE]

Jak widać wszystko śmiga poprawnie.

Podsumowanie

Pokazałem Ci jedną z głównym kolekcji do przechowywania typów wyliczeniowych – EnumSet. Pamiętaj również do c zego służy Set, ponieważ dużo częściej będziesz korzystał ze zwykłego seta i implementancji takich jak: HashSet oraz TreeSet przeznaczone do przechowywania zwykłych obiektów.

Dodatkowo istnieje jeszcze EnumMap, jest to również specjalny typ kolekcji – mapa, o której opowiem już na innym przykładzie, a nie koniecznie na EnumMap. 😉

Jeśli chcesz przyswoisz jeszcze lepiej wiedzę z EnumSet to wykonaj poniższe zadanie:

  1. Stwórz enum: Operations wraz z takimi obiektami jak: CREATE, EDIT, CLOSE, ON, SAVE, OFF, COPY, PASTE, CUT, HIBERNATE.
  2. Stwórz w klasie Main EnumSet o nazwie computerOperations oraz dodaj do niego obiekty: ON, OFF, HIBERNATE, COPY, PASTE, CUT.
  3. Stwórz w klasie Main EnumSet o nazwie textEditorOperations oraz dodaj do niej obiekty: CREATE, COPY, PASTE, CUT, SAVE.
  4. Stwórz w klasie Main EnumSet o nazwie allOperations wraz ze wszystkimi operatorami z enuma.
  5. Usuń z allOperations obiekt CREATE, ON, OFF.
  6. Wyświetl wszystkie obiekt z obu zbiorów oraz rozmiary tych zbiorów.

Moje przykładowe rozwiązanie zadania możesz zobaczyć tutaj.

 

 

Kamil Klimek

Od 2016 jestem programistą Java. Przez pierwsze 4 lata pracowałem jako Full Stack Java Developer. Później postanowiłem postawić nacisk na Javę, żeby jeszcze lepiej ją poznać.

Subscribe
Powiadom o
guest
0 komentarzy
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x