12. díl - ArrayList v Javě

Java Objektově orientované programování ArrayList v Javě

V minulém dílu tutoriálů o Javě jsme si řekli něco o datu a času. Dnes si 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 ArrayList, který 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 ArrayListu 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 ArrayListu. 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 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 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. 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.

ArrayList deklarujeme takto:

ArrayList<Integer> cisla;

Datový typ píšeme u generických kolekcí do špičatých závorek. 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.Arra­yList. V konstruktoru proměnné inicializujeme:

import java.util.ArrayList;
import java.util.Random;

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. vypis() vrátí textový řetězec pro vypsání. Ten bude obsahovat čísla z 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í ArrayListu použijeme metodu sort ze třídy Collections, která list setřídí. Bude tedy potřeba import java.util.Collec­tions. Metoda nic nevrací, pouze ArrayList setřídí uvnitř.

// import java.util.Collections;
public String vypis()
{
        String s = "";
        Collections.sort(cisla);
        for (int i : cisla)
                s += i + " ";
        return s;
}

Hotovo.

Přesuňme se do main a pomocí while cyklu umožněme uživateli ovládat objekt. Podobný program byla kalkulačka někde v 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í sc.nextLine() jako String.

Scanner sc = new Scanner(System.in, "Windows-1250");
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 = sc.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 Scanner. Vlastně můžeme nechat řešení importů na NetBeans, stačí kliknout pravým tlačítkem a zvolit FixImports, případně použít klávesovou zkratku Ctrl + Shift + I.

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í switche a provedeme příslušné akce. Pokud bylo zadáno něco jiného, pokryje to možnost default.

Losovač náhodných čísel v Javě pomocí Listu

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 úplně stejně, jako jsme pracovali s polem.

K přístupu můžeme využít metody get/set, ale pozor, prvek musí existovat. Zkusme si napsat následující kód:

ArrayList<String> l = new ArrayList<String>();
l.add("První");
System.out.println(l.get(0));
l.set(0, "První položka");
System.out.println(l.get(0));
l.set(1, "Druhá položka");  // vyhodí chybu

Vytvoříme si list Stringů. 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:

String[] poleStringu = {"První", "Druha", "Třetí"};
List<String> l = new ArrayList<String>(Arrays.asList(poleStringu));
System.out.println(l.get(2));

Kód výše vypíše "Třetí". Prvky pole se do nového listu zkopírují. Stejně můžeme předat i jiný ArrayList.

Metody na listu

  • size() - Funguje jako length na poli, vrací počet prvků v kolekci.
  • add(položka) - Metodu add() 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() - Vymaže všechny položky v listu.
  • contains(položka) - Vrací true/false podle toho, zda ArrayList obsahuje předanou položku.
  • indexOf(položka) - Vrátí index prvního výskytu položky (jako u pole). Vrací -1 při neúspěchu.
  • lastIndexOf(po­ložka) - Vrací index posledního výskytu položky v Listu. Vrací -1 při neúspěchu.
  • remove(položka) - Vymaže první nalezenou položku.
  • removeAll(index, počet) - Vymaže daný počet prvků od zadaného indexu.
  • 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() - Sort 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 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. Příště si uděláme pomocí ArrayListu databázi, bude to elektronický diář! :)


 

Stáhnout

Staženo 527x (22.32 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (11 hlasů) :
55555


 


Miniatura
Předchozí článek
Cvičení k 11. lekci OOP v Javě
Miniatura
Následující článek
Diář s databází v Javě

 

 

Komentáře
Zobrazit starší komentáře (19)

Avatar
roman64
Redaktor
Avatar
roman64:

Poznámka k příspěvku KIT z 16.1.2014. Pokud změníš prvek arrayList, který se předtím "zkopíroval" (odkazuje)z pole, tak se změna prvku nepromítne do pole (opačne to funguje - jak uvádíš).

http://www.itnetwork.cz/dev-lighter/614

Odpovědět  -1 26.6.2015 9:36
osvícený člověk se učí celý život, hlupákovi stačí hodina
Avatar
Michal Remišovský:
public int losuj()
{
        Integer cislo = random.nextInt(100) + 1;
        cisla.add(cislo);
        return cislo;
}

V metodě losuj má být 99 místo 100:

Integer cislo = random.nextInt(99) + 1;
 
Odpovědět  -1 8. května 19:07
Avatar
Nezmar Hydra
Člen
Avatar
Nezmar Hydra:

Proč mi nefunguje ve třídě Losovac:
public Mazej()
{
cisla.clear();

}

musim to napsat
public String Mazej()
{
String d = ""
cisla.clear();
return d
}
?????????????­?????????????????
Chci jen zavolat metodu Mazej nepotřebuju vracet žádné hodnoty. Jak to mám napsat "gramaticky" správně?

 
Odpovědět 19. června 0:33
Avatar
Erik Báča
Člen
Avatar
Odpovídá na Nezmar Hydra
Erik Báča:

Nepřeskakuj předchozí tutoriály, název metody se píše s malým písmenem a když metoda nemá nic vracet, tak to má vypadat takhle:

public void mazej() {
}

Ale to už bys měl dávno vědět, když se učíš arraylist

Odpovědět 19. června 0:47
Když mi dáš mínus, napiš proč!
Avatar
Nezmar Hydra
Člen
Avatar
Nezmar Hydra:

Já nepřeskakuju. Jen si prd pamatuju. ......... Omluva a díky.

 
Odpovědět 19. června 3:32
Avatar
Erik Báča
Člen
Avatar
Odpovídá na Nezmar Hydra
Erik Báča:

Já si proto to nejdůležitějšího píšu do sešitu, když si to napíšeš rukou do sešitu tak to určitě nezapomeneš a i kdyby, tak se do něj můžeš kouknout ;).

Odpovědět 19. června 11:36
Když mi dáš mínus, napiš proč!
Avatar
Nezmar Hydra
Člen
Avatar
Nezmar Hydra:

Já si psal poznáky do ukázkovejch programů....... . Sešit má něco do sebe :-)

Editováno 19. června 23:09
 
Odpovědět 19. června 23:09
Avatar
Vít Pelc
Člen
Avatar
Vít Pelc:

Mám menší problém.
Dělal jsem kód podle vzoru výše, avšak při psuštění hlásí chybu, přičemž odkazuje na určité řádky ve zdrojáku. Problémem je, že nemůžu přijít na to, na jakou chybu mě odkazuje.
Poraďte prosím

 
Odpovědět 21. listopadu 16:53
Avatar
Odpovídá na Vít Pelc
Lubomír Jahn:

Z toho co vidím můžu vyvodit jedině to že ti to vyhazuje NullPointerEx­ception protože voláš metodu losuj() na objektu, který buď neexistuje nebo má hodnotu null. Pokud ti tam nechybí vytvoření objektu Lottery l = new Lottery(); tak nevím co by mohlo být zdrojem chyby.

Editováno 28. listopadu 23:19
 
Odpovědět 28. listopadu 23:16
Avatar
Lubomír Jahn:

Z toho co vidím můžu vyvodit jedině to že ti to vyhazuje NullPointerEx­ception protože voláš metodu losuj() na objektu, který buď neexistuje nebo má hodnotu null. Pokud ti tam nechybí vytvoření objektu Losovac l = new Losovac(); tak nevím co by mohlo být zdrojem chyby.

 
Odpovědět 28. listopadu 23:20
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 29. Zobrazit vše