IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

2. diel - Java Collections Framework

V minulej lekcii, Úvod do kolekcií a genericita v Jave , sme si urobili úvod do kolekcií a ukázali sme si, čo je to genericita. V dnešnej lekcii si povieme, ako má jazyk Java kolekcie implementované. Predstavíme si základné časť z Java Collections Frameworku.

Java Collections Framework

Každý dobrý programovací jazyk ponúka v štandardnej knižnici prácu s kolekciami. V jazyku Java túto časť rieši celý framework nazvaný Java Collections Framework. Jedná sa o relatívne zložitú hierarchiu rozhranie a tried, ktoré sú dostupné všetkým programátorom. Základné vizualizácie tohto frameworku je vidieť na UML diagrame nižšie:

Zjednodušený diagram Java Collections Frameworku - Kolekcie a prúdy v Jave

Základné rozhranie, ktoré zastrešuje každú kolekciu v Jave, je rozhranie Collection. Toto rozhranie opisuje základné metódy pre prácu s každou kolekciou. Výber najdôležitejších metód je k dispozícii na obrázku nižšie:

Výpis najdôležitejších metód v rozhraní Collection - Kolekcie a prúdy v Jave

Teraz si tieto metódy popíšeme:

  • size() - vráti aktuálny počet prvkov v kolekcii
  • isEmpty() - vráti true, ak sa v kolekcii nenachádza žiadny prvok, inak false
  • contains() - vráti true, ak kolekcia obsahuje prvok z parametra
  • add() - pridá prvok do kolekcie; vráti true, ak sa zmenila kolekcia (prvok bol pridaný), inak false
  • remove() - odoberie prvok z kolekcie; vráti true, ak sa zmenila kolekcia (prvok existoval a bol odobratý), inak false
  • clear() - vymaže obsah kolekcia

Rozhranie Collection rozširuje rozhranie Iterable. Toto rozhranie definuje metódy pre prechádzanie nielen kolekcií, ale všetkých objektov, nad ktorým možno iterovat. Rozhranie obsahuje metódu iterator(), ktorú musí implementovať všetky kolekcie. Tá vracia tzv. Iterátor, ktorý si hneď vysvetlíme. Ďalej rozhranie obsahuje dve default metódy s implementáciou: forEach() a spliterator(), ktorým sa budeme venovať v ďalších lekciách.

Iterátor

Iterátory sú objekty, ktoré slúžia na prechádzanie kolekcií. Iterátor sme vlastne už použili, bez toho aby sme o tom vedeli, a to u kolekcie ArrayList.

Priechod cez indexy

Keď sme prechádzali pole, ktoré nie je plnohodnotnou kolekcií, mali sme na výber dve konštrukcie: cez indexy pomocou cyklu for:

String[] jmena = new String[] {"Karel", "Pepa", "Michal", "Vojta"};

for (int i = 0; i < jmena.length; i++) {
    System.out.println(jmena[i]);
}

A pomocou foreach:

String[] jmena = new String[] {"Karel", "Pepa", "Michal", "Vojta"};

for (String jmeno: jmena) {
    System.out.println(jmeno);
}

Keď použijeme foreach nad jednoduchým poľom, Java interne rovnako použije prístup cez indexy. Foreach je len tzv. Syntax sugar, krajší syntaxe pre programátora, ktorá sa ešte pred kompiláciou automaticky nahradí iným, typicky zložitejším kódom.

Priechod kolekcií iterátory

Pre prechádzanie skutočných kolekcií, teda zložitejších štruktúr než je pole, napr. ArrayList, môžeme tento syntaktický cukor využiť úplne rovnako. Len Java interne použije tzv. Iterátor a náš kód sa vnútorne preloží na niečo takéto:

List<String> prijmeni = new ArrayList<>();
for (Iterator<String> iterator = prijmeni.iterator(); iterator.hasNext(); ) {
    String next = iterator.next();
    System.out.println(next);
    iterator.remove(); // Pokud to kolekce podporuje, tak se odstraní aktuální prvek
}

Znalosť iterátory sa nám v praxi oplatí v prípade, keď budeme chcieť počas prehliadania z kolekcie mazať. Vtedy ich musíme pre prechádzanie explicitne použiť, viď ďalej. Ďalšie využitie Iterator je pre naše vlastné kolekcie, na ktoré následne pôjde používať foreach cyklus.

Rozhranie Iterator

Na chvíľu sa zastavíme pri rozhraní Iterator, ktoré je vrátené rovnomennú metódou. Toto rozhranie obsahuje dve dôležité metódy: next() a hasNext(). Metódy si opäť popíšme:

  • next() - vráti nasledujúce prvok
  • hasNext() - vráti true, ak existuje nasledujúci prvok

Pomocou týchto 2 metód je Java následne schopná kolekciu od začiatku do konca prejsť.

Od Javy verzie 8 sú na rozhraní tiež metódy:

  • remove() - odstráni prvok z kolekcie, ak túto operáciu kolekcie podporuje, inak sa vyvolá výnimka UnsupportedOperationException ; toto je jediný správny spôsob, ako možno odstrániť prvok z kolekcie, keď jej prechádzame
  • forEachRemaining() - prejde každý prvok kolekcie a aplikuje naň príslušnú akciu

Vlastné iterátor

Ukážme si ako implementovať vlastné iterátor, teda objekt umožňujúci priechod nejakú kolekcií. Uvažujme, že sme si vytvorili vlastnú kolekciu SimpleList, ktorá len obaľuje obyčajné pole, ktoré ju príde v konstruktoru. Triede nebudeme pridávať žiadne metódy, len ju implementujeme rozhrania Iterable a metódu iterator(), ktorá vráti anonymné implementáciu rozhrania iterátor:

public class SimpleList<Type> implements Iterable <Type> {

 private Type[] arrayList;
 private int currentSize;

 public SimpleList(Type[] newArray) {
  this.arrayList = newArray;
  this.currentSize = arrayList.length;
 }

 @Override
 public Iterator <Type> iterator() {
  Iterator <Type> it = new Iterator<Type> () {

   private int currentIndex = 0;

   @Override
   public boolean hasNext() {
    return currentIndex < currentSize && arrayList[currentIndex] != null;
   }

   @Override
   public Type next() {
    return arrayList[currentIndex++];
   }
  };
  return it;
 }
}

Trieda SimpleList prijme v konstruktoru poľa, nad ktorým sa bude vytvárať iterátor. Je dôležité, aby volanie metódy iterator() vždy vrátilo novú inštanciu Iterator u. Iterátory môžu použiť len na prechádzanie kolekcia od začiatku do konca. Ak chceme iterovat odzadu, treba najprv vytvoriť kolekciu, ktorá bude prevrátená a až nad ňou vytvoriť nový iterátor. V metóde hasNext() zisťujeme, či ak môže iterátor vrátiť ďalší prvok, alebo už došiel nakoniec. Metódou next() vrátime aktuálne prvok a zvýšime index poľa.

Všimnite si, že sme rozhranie Iterator implementovali ako anonymný triedu. Samozrejme by sme si aj mohli deklarovať plnohodnotnú triedu, napr. SimpleIterator, a v metóde iterator() vracať jej inštanciu.

Potomkovia Collection

Rozhranie Collection je rozšírené o metódy podľa spôsobu použitia pomocou rozhrania List, Set a Queue. Úplne samostatne leží rozhranie Map, ktoré obsahuje metódy pre prácu s kolekciami typu "kľúč - hodnota". Základné metódy týchto rozhraní sú implementované v abstraktných triedach podľa typu rozhrania: AbstractList, AbstractSet, AbstractQueue a AbstractMap. Abstraktné triedy sú tu použité, pretože niektoré konkrétne implementácia rozhrania môžu zdieľať implementáciu základných metód (size(), isEmpty()), ale budú mať rozdielne metódy ako je add(), remove(). Ďalej sú tieto abstraktné triedy užitočné v prípade, že si budete chcieť implementovať vlastnú kolekciu, ale chcete mať už nejaký základ implementovaný.

Aby som bol úplne presný, tak všetky vyššie vymenované abstraktné triedy okrem AbstractMap ešte dedí od spoločnej abstraktné triedy AbstractCollection. Všetky triedy možno nájsť v balíčku java.util. Tieto triedy majú jednu spoločnú vlastnosť: nie sú thread-safe. To znamená, že nemajú zabezpečenia pre modifikáciu prvkov z viacerých vlákien. Tento problém je v Jave riešený pomocou tried, ktoré sa nachádzajú v balíčku java.util.concurrent. Tu sa okrem iného nachádzajú rovnomennej triedy s podporou modifikácie z viacerých vlákien. Napríklad pre ArrayList tú existuje thread-safe verzia v podobe CopyOnWriteArrayList.

V ďalších lekciách postupne preberieme najdôležitejšie rozhranie List, Set, Queue a Map a ich implementácie, konkrétne ArrayList, LinkedList, HashSet a HashMap. Nabudúce nás čaká Zoznam (List) pomocou poľa v Jave .


 

Predchádzajúci článok
Úvod do kolekcií a genericita v Jave
Všetky články v sekcii
Kolekcie a prúdy v Jave
Preskočiť článok
(neodporúčame)
Zoznam (List) pomocou poľa v Jave
Článok pre vás napísal Petr Štechmüller
Avatar
Užívateľské hodnotenie:
1 hlasov
Autor se věnuje primárně programování v Javě, ale nebojí se ani webových technologií.
Aktivity