11. diel - ArrayList v Jave
V predchádzajúcom kvíze, Kvíz - Dedičnosť, statika, gettery a settery v Jave OOP, sme si overili nadobudnuté skúsenosti z predchádzajúcich lekcií.
Dnes si v tutoriáli ukážeme jednu kolekciu, ktorá je múdrejší, než pole. Umožňuje totiž prvky ľubovoľne pridávať a mazať.
Pojem kolekcie sme tu už spomínali. Je to štruktúra, do ktorej môžeme
ukladať viacero objektov. Kolekcií je v Jave veľké množstvo, sú
uspôsobené na rôzne účely a môžeme s nimi zaobchádzať rôznymi
spôsobmi. Preto im je venovaná celá sekcia. Doteraz poznáme iba kolekciu
poľa. V priebehu seriálu však budeme potrebovať niečo múdrejšie, kam
budeme môcť jednoducho za behu programu pridávať a mazať
záznamy. Iste by sa nám hodilo si v pamäti spravovať databázu
nejakých objektov. Vieme, že pole má konštantnú veľkosť, čo je daň za
jeho vysokú rýchlosť. Teraz si predstavíme triedu ArrayList
,
ktorú môžeme už podľa názvu chápať ako nadstavbu
poľa.
ArrayList
ArrayList
je tzv. generická kolekcia. Pojem
genericita si plne vysvetlíme až pri kolekciách, teraz nám bude stačiť
vedieť, že pri deklarácii kolekcie ArrayList
špecifikujeme
dátový typ objektov, ktoré v ňom budú uložené. Začnime jednoducho a
urobme si ArrayList
čísel, ktoré budeme náhodne žrebovať.
Žrebovanie
Program sa nás vždy spýta, či chceme losovať ďalšie číslo a to sa
pridá do kolekcie ArrayList
. Pokiaľ už nebudeme chcieť
žrebovať, program vypíše žrebované čísla, zoradené od najmenšieho po
najväčšie. Založme si nový projekt Losovani
a vytvorme si
triedu Losovac
. Trieda bude obsahovať kolekciu
ArrayList
typu Integer
, kde budú čísla
uložené.
Narážame na triedu Integer
, ktorá slúži na uloženie
celých čísel av podstate obaľuje dátový typ int
. Do
ArrayListu sa totiž dajú vkladať iba objekty, teda premenné
referenčného typu. Na tieto účely existuje typ Integer
. Ku
každému primitívnemu typu v Jave existuje jeho referenčný "obal", čoskoro
si ich uvedieme. Kolekcia ArrayList
bude privátna a bude slúžiť
iba ako interné úložisko danej triedy, aby sa naň zvonku nedalo
pristupovať.
Kolekciu ArrayList
deklarujeme takto:
ArrayList<Integer> cisla;
Dátový typ píšeme pri generických kolekciách do špicatých
zátvoriek. Kolekcia ArrayList
je samozrejme objekt, ako
každý iný. Rovnako ako pri poli a iných objektoch, aj tu premennú pred
použitím inicializujeme:
ArrayList<Integer> cisla = new ArrayList<Integer>();
Všimnite si zátvorku, ktorú značí konštruktor. Takýto list teda
umiestnime do našej triedy, spolu s náhodným generátorom
Random
. Pre prácu s triedou ArrayList
je potrebné
pridať import java.util.ArrayList
. V konštruktore atribúty
inicializujeme:
import java.util.ArrayList; import java.util.Random; public class Losovac { private ArrayList<Integer> cisla; private Random random; public Losovac() { random = new Random(); cisla = new ArrayList<Integer>(); } }
Ďalej pridáme metódy losuj()
a vypis()
, kde
losuj()
pridá do ArrayListu nové náhodné číslo a
taktiež ho vráti ako návratovú hodnotu. Metóda vypis()
vráti
textový reťazec na vypísanie. Ten bude obsahovať čísla z kolekcie
cisla
, zoradené a oddelené medzerou.
Žrebovanie náhodného čísla už poznáme z dielu o hracej kocke, tu
budeme vyhadzovať čísla od 1
do 100
. Číslo do
ArrayListu pridáme pomocou metódy add()
:
public int losuj() { Integer cislo = random.nextInt(100) + 1; cisla.add(cislo); return cislo; }
Veľmi jednoduché, že? Kolekcia ArrayList
je interne pomerne
zložitá a zatiaľ sa nebudeme zaoberať tým, čo sa vo vnútri deje. To je
napokon účel Javy, ponúkať kvalitné a sofistikované komponenty, ktoré sa
jednoducho používajú.
Výpis čísel bude ešte jednoduchší. Na zotriedenie kolekcie
ArrayList
použijeme metódu sort()
z triedy
Collections
, ktorá list zotriedi. Bude teda potrebné importovať
java.util.Collections
. Metóda nič nevracia, iba
ArrayList
zotriedi vo vnútri:
public String vypis() { String vypis = ""; Collections.sort(cisla); for (int cislo : cisla) { vypis += cislo + " "; } return vypis; }
Hotovo.
Presuňme sa do metódy main()
a pomocou cyklu
while
umožnime užívateľovi ovládať objekt. Podobný program
bola kalkulačka z prvých lekcií, kde sme sa v cykle pýtali, či si
užívateľ praje opakovať výpočet. Tu budeme postupovať totožne.
Ovládanie bude pomocou možností 1
, 2
,
3
(losuj, vypíš, koniec). Budeme ich načítať pomocou metódy
scanner.nextLine()
ako String
:
Scanner scanner = new Scanner(System.in); Losovac losovac = new Losovac(); System.out.println("Vitajte v programe žrebovania."); String volba = "0"; // hlavný cyklus while (!volba.equals("3")) { // výpis možností System.out.println("1 - Losovať ďalšie číslo"); System.out.println("2 - Vypísať čísla"); System.out.println("3 - Koniec"); volba = scanner.nextLine(); System.out.println(); // reakcia na voľbu switch (volba) { case "1": System.out.printf("Padlo číslo: %s%n", losovac.losuj()); break; case "2": System.out.printf("Padla čísla: %s%n", losovac.vypis()); break; case "3": System.out.println("Ďakujem za použitie programu"); break; default: System.out.println("Neplatná voľba, zadajte prosím znova."); break; } }
Nezabudneme na import triedy Scanner
. IDE väčšinou toto
zvládne robiť za nás
- V IntelliJ stačí napríklad stlačenie
klávesu Tab pri písaní triedy
Scanner
: - V NetBeans stačí kliknúť pravým tlačidlom na triedu
Scanner
a zvoliť z ponuky Fix imports, prípadne použiť klávesovú skratku Ctrl + Shift + I.
switch
a vykonáme príslušné akcie. Pokiaľ bolo zadané niečo
iné, pokryje to možnosť default
:
Konzolová aplikácia
3 - Koniec
1
Padlo číslo: 52
1 - Losovať ďalšie číslo
2 - Vypísať čísla
3 - Koniec
1
Padlo číslo: 40
1 - Losovať ďalšie číslo
2 - Vypísať čísla
3 - Koniec
1
Padlo číslo: 62
1 - Losovať ďalšie číslo
2 - Vypísať čísla
3 - Koniec
2
Padla čísla: 2 6 7 7 8 8 9 9 10 10 12 14 17 19 19 21 23 25 25 27 27 27 28 28 28 30 30 31 32 33 33 35 35 36 36 36 37 38 38 40 41 42 42 42 44 45 45 45 45 45 48 51 52 52 53 55 56 56 56 57 58 58 59 61 62 66 68 68 71 72 73 73 74 76 82 83 84 84 85 87 88 88 89 90 90 91 93 94 98 98 98 99 100
1 - Losovať ďalšie číslo
2 - Vypísať čísla
3 - Koniec
Vidíme, že môžeme stále pridávať nové a nové čísla. Máme oveľa väčšie možnosti ako s poľom. Zároveň však môžeme s ArrayListom pracovať podobne, ako sme pracovali s poľom.
Na prístup môžeme využiť metódy get()
a
set()
, ale pozor, prvok musí existovať. Skúsme si napísať
nasledujúci kód:
ArrayList<String> polozky = new ArrayList<String>(); polozky.add("Prvá"); System.out.println(polozky.get(0)); polozky.set(0, "Prvá položka"); System.out.println(polozky.get(0)); polozky.set(1, "Druhá položka"); // vyhodí chybu
Vytvoríme si list textových reťazcov. Pridáme položku
Prvá
a potom vypíšeme položku na indexe 0
.
Vypíše sa nám První
. Môžeme na ňu samozrejme aj takto
zapisovať. S druhou položkou na pozícii 1
však už nemôžeme
pracovať, pretože sme ju do listu nepridali. Pri poli sme zadali veľkosť a
on všetky "priehradky" (premenné pod indexy) založil. Teraz veľkosť
nezadávame a "priehradky" si pridávame sami.
Pozrime sa na ArrayList
podrobnejšie a vypíšme si metódy,
ktoré sú pre nás teraz zaujímavé.
Konštruktory
Okrem prázdneho ArrayListu môžeme List
vytvoriť aj
ako kópiu z iného listu, poľa alebo inej kolekcie. Stačí kolekciu odovzdať
do konštruktora:
{JAVA_OOP}
import java.util.ArrayList;
import java.util.Arrays;
{JAVA_MAIN_BLOCK}
String[] retezce = {"Prvá", "Druhá", "Tretí"};
ArrayList<String> polozky = new ArrayList<String>(Arrays.asList(retezce));
System.out.println(polozky.get(2));
{/JAVA_MAIN_BLOCK}
{/JAVA_OOP}
Kód vyššie vypíše Třetí
:
Konzolová aplikácia
Tretí
Prvky poľa sa do nového hárka skopírujú. Rovnako môžeme odovzdať aj
iný ArrayList
.
Metódy na triede
ArrayList
Ukážeme si pár dôležitých metód, ktoré môžeme volať na triede
ArrayList
:
size()
- Funguje ako metódalength()
na poli, vracia počet prvkov v kolekcii.add(položka)
- Metóduadd()
sme si už vyskúšali, ako parameter berie položku, ktorú vloží do listu.addAll(kolekce)
- Pridá do listu viac položiek, napr. z poľa.clear()
- Odstráni všetky položky v liste.contains(položka)
- Vracia hodnotytrue
alebofalse
podľa toho, čiArrayList
obsahuje odovzdanú položku.indexOf(položka)
- Vráti index prvého výskytu položky (ako pri poli). Vracia hodnotu-1
pri neúspechu.lastIndexOf(položka)
- Vracia index posledného výskytu položky v liste. Vracia hodnotu-1
pri neúspechu.remove(index)
- Odstráni položku na danom indexe.removeAll(kolekce)
- Odstráni všetky položky v liste (podobná ako metódaclear()
, ale pomalšia - robí ďalšie kroky navyše)toArray()
- Skopíruje položky z ArrayListu do poľa a to vráti.
Ďalšie metódy a pre prácu s listom nájdeme v triede
Collections
. Ako parameter berú danú kolekciu:
min()
- Vráti najmenší prvok z kolekcie.max()
- Vráti najväčší prvok z kolekcie.reverse()
- Obráti list tak, že je prvá položka posledná a naopak. Metóda nič nevracia, zmeny sa vykonajú v zadanom liste.sort()
- Metódusort()
už tiež poznáme, zotriedi položky v liste. Metóda opäť nič nevracia.
ArrayList
toho dokáže oveľa viac ako
pole. Najväčšou výhodou je pridávanie a mazanie prvkov. Daň vo výkone je
zanedbateľná. V sekcii s kolekciami zistíme, že kolekcia
ArrayList
má ešte ďalšie metódy, ale zatiaľ nemáme
skúsenosti.
Program pre ukladanie žrebovaných čísel bol zaujímavý, ale iste sa nám bude v budúcnosti hodiť ukladať skôr plnohodnotné objekty, než čísla.
V nasledujúcom cvičení, Riešené úlohy k 11. lekcii OOP v Jave, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 1008x (23.1 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java