Java (10) - Kontejnery I.
Kontejnery (v Javě obvykle nazývané "kolekce") jsou objekty, které nám umožňují
snadno a efektivně spravovat variabilní hromadná data. Dají se s nimi
dělat úžasné věci.
23.3.2005 15:00 |
Lukáš Jelínek
| Články autora
| přečteno 77992×
Úvod do problematiky
Proč kontejnery
Pole, s nimiž jsme se seznámili v předchozích kapitolách, mají několik zásadních nevýhod.
Nemohou měnit svoji velikost (mají předem daný počet prvků), lze k nim přistupovat jen podle
číselného indexu, řazení prvků se musí provádět externě a explicitně, k manipulacím s poli
nelze přidávat vedlejší efekty (které se někdy hodí). Proto už hodně dávno vzniklo něco,
čemu se obecně říká kontejnery.
Kontejner je datový objekt, obsahující "v sobě" nějaké další objekty, ke kterým lze
různým způsobem přistupovat a pracovat s nimi. Podle způsobů uložení dat a práce s nimi
rozlišujeme různé druhy kontejnerů a při jejich použití si vždy vybereme ten, který
se pro daný případ nejlépe hodí.
V Javě se kontejnerům většinou říká kolekce (proto budu v dalším textu používat i tento termín),
jejich chování se částečně podobá kontejnerům, které programátoři v C++ znají z knihovny STL.
S javovskými kolekcemi se však pracuje trochu odlišně - dá se říci názorněji, avšak za cenu
většího množství napsaného kódu.
The Collections Framework
Pod tímto názvem (dále budu používat "CF") se skrývá celý systém rozhraní a tříd, které bezprostředně
souvisí s kolekcemi. Naprostou většinu z nich najdeme v balíku java.util (na jiné umístění včas
upozorním). Důležitým faktem je, že v Javě 5.0 (tj. od JDK 1.5.0) došlo v CF k významným změnám
(které CF částečně posunuly směrem k STL). Všechna další vysvětlení a příklady se budou týkat JDK verze
1.4.2, změny provedené ve verzi 1.5.0 uvedu na závěr.
Práce s kolekcemi se rozhodně neomezuje jen na knihovnu CF, právě naopak. S výhodou si můžeme vytvářet vlastní
kontejnery a implementovat např. různé vedlejší efekty operací, vlastní způsob uložení dat (když
to hodně přeženu, kontejner lze třeba i přímo napojit na databázi), přidávat své vlastní operace
atd. Kdo si dobře zažije práci s hotovými objekty, sám přijde na to, co mu případně chybí.
Důležité pojmy
I když není dobré přehánět to se suchou teorií, zde se jí (v zájmu dobrého pochopení funkce
jednotlivých kontejnerů) težko vyhneme. Ale nebude jí mnoho...
Iterátor je prostředek zajišťující sekvenční přístup k datům. Pracuje krokově, v každém dalším
poskytne přístup k dalšímu prvku. Používá se tehdy, když potřebujeme postupně pracovat
s jednotlivými prvky a buď nezáleží na pořadí, nebo pořadí vyplývá z vlastností kolekce, nad níž
iterátor pracuje. Potřebujeme-li pracovat s prvky právě tímto způsobem (např. z každého něco
přečíst), měli bychom vždy používat iterátory, protože bývají implementovány tak, aby to pro
uvedené použití bylo nejrychlejší.
Porovnatelnost objektů je důležitá vlastnost, kterou potřebujeme pro uložení do některých kontejnerů.
Je to tehdy, když se objekty uspořádávají v přirozeném pořadí (v základním způsobu uspořádání).
Zjišťuje se, zda jsou objekty sobě rovny, nebo je jeden z nich "větší" či "menší" než druhý
(u číselných hodnot je význam jasný; ostatní datové objekty mohou mít porovnatelnost implementovánu
prakticky libovolným způsobem). V Javě je porovnatelnost zaručena tím, že třída implementuje
rozhraní Comparable (obsahuje jedinou metodu compareTo() ).
Většina standardních tříd rozhraní Comparable neimplementuje - ani tam není vše ztraceno.
Můžeme totiž vytvořit tzv. komparátor (rozhraní Comparator ), který lze použít neomezeně,
s libovolnými objekty (záleží pouze na jeho implementaci). Komparátor zajišťuje úplné
uspořádání objektů (pomocí operací porovnání a testu rovnosti), můžeme ho použít jak
při explicitním řazení prvků, tak ho předat některým kolekcím pro použití k vnitřnímu
uspořádání.
Volba vhodného kontejneru
I když u každého typu kontejneru vždy vysvětlím, k čemu se daný typ hodí, obecný úvod udělám
ihned. Máme totiž k dispozici širokou škálu kolekcí v různých kategoriích a správná
volba je důležitá z hlediska dobré funkce programu a jeho rychlosti. Obvykle posuzujeme tato
hlediska:
-
Způsob práce (sekvenční nebo náhodný přístup) - různé typy kontejnerů se hodí pro určité
způsoby přístupu, je nutné s tím předem počítat. Lze říci, že kolekce vhodné pro náhodný
přístup se dají docela dobře použít i pro přístup sekvenční, ale spotřebuje se vždy
více paměti, než by bylo nutné při volbě kolekce přímo pro sekvenční přístup.
-
Četnost čtení, přidávání, odebírání, přesunů - platí totéž co pro náhodný a sekveční přístup.
Je dobré si toto předem ujasnit, při nejasnosti provést během ladění testy s různými typy
kolekcí a měřit rychlost a spotřebu paměti (i když se to někdy dělá dost špatně). Je třeba
si rovněž uvědomit, že ne všechny kontejnery musí nutně implementovat všechny manipulační
operace.
-
Vláknová bezpečnost - k vláknům se dostaneme sice až někdy později, ale už teď je důležité,
že by během manipulačních operací kontejneru (kdy je kontejner v nekonzistentním stavu) k němu
nemělo přistupovat více vláken. Musí se "nějak" zajistit synchronizace přístupu - některé
kolekce synchronizaci obsahují (spíše ty starší), jiné nikoliv (je to rychlejší). Pokud použijeme
kontejner bez synchronizace a mohlo by dojít k současnému přístupu více vláken, je třeba
synchronizovat přístup přímo v programu.
-
Volba vhodného rozhraní - při vlastní práci s kolekcemi (kromě jejich vytváření) je vhodné
používat rozhraní, která jsou společná většímu počtu kolekcí. Kód je pak obecnější a usnadní
se tím případná změna implementační třídy kolekce.
Poznámky pro programátory v C++
Tvůrci Javy říkají, že zatímco v STL jsou středobodem iterátory, v javovských kolekcích jsou
podružnou záležitostí - v řadě případů se obejdeme bez nich. Skutečně, u spousty použití
kontejnerů v Javě o iterátory ani nezavadíme. Dostaneme se k tomu později v příkladech.
Příjemnou věcí je naopak fakt, že narozdíl od STL se javovské kolekce chovají na všech platformách
stejně (jako většina věcí v Javě). Další podstatný rozdíl je ten, že v Javě se obecně nevyskytují (až na malé
výjimky), narozdíl od C++, přetížené operátory - to platí i pro kontejnery a s nimi spojené iterátory.
Pracujeme s nimi prostřednictvím volání různých metod.
Základy práce s kolekcemi
Jednoduchý příklad
Než se pustíme do postupného poznávání světa The Collections Framework, bude dobré si nejprve ukázat,
co to vlastně umí. Jako příklad jsem zvolil práci se třídou Vector , která byla jednou
z prvních implementací kontejnerů (ještě před vznikem CF) a představuje vlastně pole s proměnnou velikostí:
Vector v = new Vector(); // vytvoří instanci s výchozími parametry
v.add("abcd"); // vloží textový řetězec
v.add(new Integer(6)); // vloží celé číslo
v.add(1, "efgh"); // vloží textový řetězec na pozici 1
System.out.println("Na pozici 1 je: " + v.elementAt(1));
System.out.println("Obsah vektoru:");
Iterator it = v.iterator();
while (it.hasNext()) { // opakuj, dokud jsou položky
System.out.println(it.next()); // tisk další položky
}
v.clear(); // smazání obsahu
V uvedeném příkladě se vytvoří instance třídy Vector s výchozími parametry. Pak do něj
přidáme tři objekty: řetězec (přidá se na konec), celé číslo (opět na konec) a znovu řetězec (vloží
se na pozici 1, data od této pozice se tím posunou). Indexy se (stejně jako u polí) číslují od
nuly. Pokud chceme vložit primitivní datový objekt, musíme použít "zapouzdřující" referenční
typ - v tomto případě pro int použijeme typ Integer .
Na dalším řádku je vidět přímý přístup k prvku přes jeho index. Metoda elementAt
pracuje obdobně jako operátor hranatých závorek u polí - a to včetně toho, že se při přístupu mimo
platný rozsah vyvolá výjimka ArrayIndexOutOfBoundsException . Co se naopak liší,
je vrácený typ. U polí jsme zvyklí na to, že máme vždy hodnotu toho typu, jakého je pole. U kolekcí
tomu tak není, prvky se vrací jako typ Object a o správné přetypování se musíme
postarat sami. Ve výše uvedeném případě na tom nezáleží, neboť se stejně vše převede na řetězec.
Pak tu máme ukázku práce s iterátorem. Ten získáme obecně metodou iterator() a pracujeme
s ním pomocí dvojice metod hasNext() (zjistí, zda jsou k dispozici další položky)
a next() (vrátí následující položku). Prvky jsou opět v podobě referencí na Object .
Závěrečné volání vymaže obsah celého vektoru (odstraní všechny položky).
Výše uvedený příklad a další podobný (složitější) najdete i s komentáři v ukázkovém zdrojovém souboru
ContainerExample.java ,
který si můžete stáhnout a zkompilovat. Pozn.: Pokud budete zkoušet kompilovat na Javě 5.0
(JDK 1.5.x), kompilátor vypíše varování. Nedělejte si s ním starosti, brzy si řekneme, proč to
dělá.
Podrobnější seznámení s kolekcemi
Doufám, že jsem vás tímto nezáživným, obecným a téměř ryze teoretickým úvodem do světa javovských
kontejnerů neznechutil natolik, že byste o ně ztratili zájem. Byla by to škoda, příště totiž
přijde řada na jednotlivé kategorie a konkrétní implementace kolekcí - jak pracují, co umí a neumí,
k čemu se hodí a jak je správně použít.
Verze pro tisk
|
Příspívat do diskuze mohou pouze registrovaní uživatelé.
|
|

Vyhledávání software

Vyhledávání článků
28.11.2018 23:56 /František Kučera Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1
12.11.2018 21:28 /Redakce Linuxsoft.cz 22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář
6.11.2018 2:04 /František Kučera Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
4.10.2018 21:30 /Ondřej Čečák LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář
18.9.2018 23:30 /František Kučera Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
9.9.2018 14:15 /Redakce Linuxsoft.cz 20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business.
Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář
12.8.2018 16:58 /František Kučera Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář
16.7.2018 1:05 /František Kučera Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář
Více ...
Přidat zprávičku
 Poslední diskuze
31.7.2023 14:13 /
Linda Graham iPhone Services
30.11.2022 9:32 /
Kyle McDermott Hosting download unavailable
13.12.2018 10:57 /
Jan Mareš Re: zavináč
2.12.2018 23:56 /
František Kučera Sraz
5.10.2018 17:12 /
Jakub Kuljovsky Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?
Více ...
|