Lekce 13 - ArrayList v Javě
V předchozím kvízu, Kvíz - Dědičnost, statika, gettery a settery v Javě OOP, jsme si ověřili nabyté zkušenosti z předchozích lekcí.
Dnes si v tutoriálu ukážeme jednu kolekci, která je chytřejší, než pole. Umožňuje totiž prvky libovolně přidávat a mazat.
Pojem kolekce jsme tu již zmínili. Je to struktura, do které můžeme
ukládat více objektů. Kolekcí je v Javě velké množství, jsou uzpůsobeny
na různé účely a můžeme s nimi zacházet různými způsoby. Proto jim je
věnována celá sekce. Dosud známe pouze kolekci pole. V průběhu seriálu
však budeme potřebovat něco chytřejšího, kam budeme moci jednoduše za
běhu programu přidávat a mazat záznamy. Jistě by se nám
hodilo si v paměti spravovat databázi nějakých objektů. Víme, že pole má
konstantní velikost, což je daň za jeho vysokou rychlost. Nyní si
představíme třídu ArrayList, kterou můžeme již podle
názvu chápat jako nadstavbu pole.
ArrayList
ArrayList je tzv. generická kolekce. Pojem
genericita si plně vysvětlíme až u kolekcí, nyní nám bude stačit
vědět, že při deklaraci kolekce ArrayList specifikujeme datový
typ objektů, které v něm budou uloženy. Začněme jednoduše a udělejme si
ArrayList čísel, která budeme náhodně losovat.
Losování
Program se nás vždy zeptá, zda chceme losovat další číslo a to se
přidá do kolekce ArrayList. Pokud již nebudeme chtít losovat,
program vypíše losovaná čísla, seřazená od nejmenšího po největší.
Založme si nový projekt Losovac a vytvořme v něm stejnojmennou
třídu Losovac. Třída bude obsahovat kolekci
ArrayList typu Integer, kde budou čísla
uložena.
Narážíme na třídu Integer, která slouží k uložení
celých čísel a v podstatě obaluje datový typ int. Do
ArrayListu se totiž dají vkládat pouze objekty, tedy proměnné
referenčního typu. Pro tyto účely existuje typ Integer. Ke
každému primitivnímu typu v Javě existuje jeho referenční "obal", brzy si
je uvedeme. Kolekce ArrayList bude privátní a bude sloužit pouze
jako interní úložiště dané třídy, aby se na něj zvenku nedalo
přistupovat.
Kolekci ArrayList deklarujeme takto:
ArrayList<Integer> cisla;
Datový typ píšeme u generických kolekcí do špičatých
závorek. Kolekce ArrayList je samozřejmě objekt, jako
každý jiný. Stejně jako u pole a jiných objektů, i zde proměnnou před
použitím inicializujeme:
ArrayList<Integer> cisla = new ArrayList<Integer>();
Všimněte si závorek, které značí konstruktor. Takovýto list tedy
umístíme do naší třídy, spolu s náhodným generátorem
Random. Pro práci s třídou ArrayList je třeba
přidat import java.util.ArrayList. V konstruktoru atributy
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>(); } }
Dále přidáme metody losuj() a vypis(), kde
losuj() přidá do ArrayListu nové náhodné číslo a
také ho vrátí jako návratovou hodnotu. Metoda vypis() vrátí
textový řetězec pro vypsání. Ten bude obsahovat čísla z kolekce
cisla, seřazená a oddělená mezerou.
Losování náhodného čísla již známe z dílu o hrací kostce, zde
budeme vyhazovat čísla od 1 do 100. Číslo do
ArrayListu přidáme pomocí metody add():
public int losuj() { Integer cislo = random.nextInt(100) + 1; cisla.add(cislo); return cislo; }
Velmi jednoduché, že? Kolekce ArrayList je interně poměrně
složitá a zatím se nebudeme zabývat tím, co se uvnitř děje. To je
ostatně účel Javy, nabízet kvalitní a sofistikované komponenty, které se
jednoduše používají.
Výpis čísel bude ještě snazší. K setřídění kolekce
ArrayList použijeme metodu sort() ze třídy
Collections, která list setřídí. Bude tedy potřeba importovat
java.util.Collections. Metoda nic nevrací, pouze
ArrayList setřídí uvnitř:
public String vypis() { String vypis = ""; Collections.sort(cisla); for (int cislo : cisla) { vypis += cislo + " "; } return vypis; }
Hotovo.
Přesuňme se do metody main() a pomocí cyklu
while umožněme uživateli ovládat objekt. Podobný program byla
kalkulačka z prvních lekcí, kde jsme se v cyklu ptali, zda si uživatel
přeje opakovat výpočet. Zde budeme postupovat totožně.
Ovládání bude pomocí možností 1, 2,
3 (losuj, vypiš, konec). Budeme je načítat pomocí metody
scanner.nextLine() jako String:
Scanner scanner = new Scanner(System.in); Losovac losovac = new Losovac(); System.out.println("Vítejte v programu losování."); String volba = "0"; // hlavní cyklus while (!volba.equals("3")) { // výpis možností System.out.println("1 - Losovat další číslo"); System.out.println("2 - Vypsat čísla"); System.out.println("3 - Konec"); volba = scanner.nextLine(); System.out.println(); // reakce na volbu 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("Děkuji za použití programu"); break; default: System.out.println("Neplatná volba, zadejte prosím znovu."); break; } }
Nezapomeneme na import třídy Scanner. IDE většinou toto
zvládne dělat za nás 
V IntelliJ stačí například stisknutí klávesy Tab při psaní
třídy Scanner:

Průběh programu je z kódu dobře viditelný, nejprve nastavíme volbu na
nějakou výchozí hodnotu, aby cyklus poprvé proběhl. Poté volbu načteme z
klávesnice. String zpracujeme pomocí konstrukce switch a
provedeme příslušné akce. Pokud bylo zadáno něco jiného, pokryje to
možnost default:
Konzolová aplikace
3 - Konec
1
Padlo číslo: 52
1 - Losovat další číslo
2 - Vypsat čísla
3 - Konec
1
Padlo číslo: 40
1 - Losovat další číslo
2 - Vypsat čísla
3 - Konec
1
Padlo číslo: 62
1 - Losovat další číslo
2 - Vypsat čísla
3 - Konec
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 - Losovat další číslo
2 - Vypsat čísla
3 - Konec
Vidíme, že můžeme stále přidávat nová a nová čísla. Máme mnohem větší možnosti než s polem. Zároveň však můžeme s ArrayListem pracovat podobně, jako jsme pracovali s polem.
K přístupu můžeme využít metody get() a
set(), ale pozor, prvek musí existovat. Zkusme si napsat
následující kód:
ArrayList<String> polozky = new ArrayList<String>(); polozky.add("První"); System.out.println(polozky.get(0)); polozky.set(0, "První položka"); System.out.println(polozky.get(0)); polozky.set(1, "Druhá položka"); // vyhodí chybu
Vytvoříme si list textových řetězců. Přidáme položku
První a poté vypíšeme položku na indexu 0.
Vypíše se nám První. Můžeme na ni samozřejmě i takto
zapisovat. S druhou položkou na pozici 1 však již nemůžeme
pracovat, protože jsme ji do listu nepřidali. U pole jsme zadali velikost a on
všechny "přihrádky" (proměnné pod indexy) založil. Nyní velikost
nezadáváme a "přihrádky" si přidáváme sami.
Podívejme se na ArrayList podrobněji a vypišme si metody,
které jsou pro nás nyní zajímavé.
Konstruktory
Kromě prázdného ArrayListu můžeme List vytvořit i
jako kopii z jiného listu, pole nebo jiné kolekce. Stačí kolekci předat do
konstruktoru:
{JAVA_OOP}
import java.util.ArrayList;
import java.util.Arrays;
{JAVA_MAIN_BLOCK}
String[] retezce = {"První", "Druhá", "Třetí"};
ArrayList<String> polozky = new ArrayList<String>(Arrays.asList(retezce));
System.out.println(polozky.get(2));
{/JAVA_MAIN_BLOCK}
{/JAVA_OOP}
Kód výše vypíše Třetí:
Konzolová aplikace
Třetí
Prvky pole se do nového listu zkopírují. Stejně můžeme předat i jiný
ArrayList.
Metody na třídě
ArrayList
Ukážeme si pár důležitých metod, které můžeme volat na třídě
ArrayList:
size()- Funguje jako metodalength()na poli, vrací počet prvků v kolekci.add(položka)- Metoduadd()jsme si již vyzkoušeli, jako parametr bere položku, kterou vloží do listu.addAll(kolekce)- Přidá do listu více položek, např. z pole.clear()- Odstraní všechny položky v listu.contains(položka)- Vrací hodnotytruenebofalsepodle toho, zdaArrayListobsahuje předanou položku.indexOf(položka)- Vrátí index prvního výskytu položky (jako u pole). Vrací hodnotu-1při neúspěchu.lastIndexOf(položka)- Vrací index posledního výskytu položky v listu. Vrací hodnotu-1při neúspěchu.remove(index)- Odstraní položku na daném indexu.removeAll(kolekce)- Odstraní všechny položky v listu (podobná jako metodaclear(), ale pomalejší - dělá další kroky navíc)toArray()- Zkopíruje položky z ArrayListu do pole a to vrátí.
Další metody
Další metody a pro práci s listem najdeme ve třídě
Collections. Jako parametr berou danou kolekci:
min()- Vrátí nejmenší prvek z kolekce.max()- Vrátí největší prvek z kolekce.reverse()- Obrátí list tak, že je první položka poslední a naopak. Metoda nic nevrací, změny se provedou v zadaném listu.sort()- Metodusort()již také známe, setřídí položky v listu. Metoda opět nic nevrací.
Vidíme, že kolekce ArrayList toho umí mnohem více, než
pole. Největší výhodou je přidávání a mazání prvků. Daň ve výkonu
je zanedbatelná. V sekci s kolekcemi zjistíme, že kolekce
ArrayList má ještě další metody, ale zatím na to nemáme
zkušenosti.
Program pro ukládání losovaných čísel byl zajímavý, ale jistě se nám bude v budoucnu hodit ukládat spíše plnohodnotné objekty, než čísla.
V následujícím cvičení, Řešené úlohy k 13. lekci OOP v Javě, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 1172x (7.33 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

David se informační technologie naučil na