Lekce 11 - 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 Losovani
a vytvořme si 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ích, 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í hodnotytrue
nebofalse
podle toho, zdaArrayList
obsahuje předanou položku.indexOf(položka)
- Vrátí index prvního výskytu položky (jako u pole). Vrací hodnotu-1
při neúspěchu.lastIndexOf(položka)
- Vrací index posledního výskytu položky v listu. Vrací hodnotu-1
př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 11. 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 1069x (23.1 kB)
Aplikace je včetně zdrojových kódů v jazyce Java