2. diel - Zoznam (List) pomocou poľa vo VB.NET
V minulej lekcii, Úvod do kolekcií a genericita , sme si urobili úvod do kolekcií a ukázali sme si, čo je to genericita.
Dnes sa budeme v VB .NET tutoriálu venovať zoznamom (List
),
čo je typ kolekciou, s ktorým sme sa počas seriálu už stretli.
Poľa
Urobme si na začiatku malú odbočku späť k poľu, ktoré bolo prvou kolekciou, ktorú sme v seriáli spoznali. Pole sa vyznačuje tým, že má pevne daný počet prvkov (ak nebudeme uvažovať tzv. Dynamická pole). Z tohto dôvodu sa dokonca niekedy považované za kolekciu, jedná sa o dátovú štruktúru. Prvky v poli sú číselne indexované a to od nuly.
Hlavnou nevýhodou poľa teda je, že do neho nemôžeme za behu aplikácie prvky pridávať alebo ich mazať. To bohužiaľ často potrebujeme, aj keď sú situácie, kedy je pole ideálna voľba. Touto daní je vyvážená obrovská rýchlosť, s ktorou môžeme s prvkami poľa pracovať. Keďže dáta sú rovnakého typu (či už úplne rovnakého, alebo spoločného predka), tak prvky poľa zaberajú v pamäti rovnako miesta. Jednotlivé prvky poľa sú v pamäti uložené za sebou, ako v rade, ktorá je neprerušená. Pole celých čísel si môžeme predstaviť napr. Nasledovne:
Ak teda chceme napr. Pristúpiť na piaty prvok (prvok s indexom
4), len vstúpime tam, kde pole začína a potom odskočíme štyri
násobky veľkosti typu (tu Integer
) ďalej. Sme na piatom prvku.
Čítanie a zápis na indexy v poli má teda konštantný
časovú zložitosť. Ak vás tento termín zmiatol, môžete to
chápať tak, že do poľa zapisujeme okamžite a rovnako tak z neho aj
čítame.
Ak v VB .NET založíme prázdne číselné pole, je automaticky naplnené nulami.
Zoznamy (Listy)
Zoznamy (anglicky a často i slovensky list) sú kolekcie, ktoré umožňujú prvky za behu programu pridávať a mazať. Môžu byť číselne indexované ako polia, ale tiež nemusí. Sú v zásade dva typy zoznamov.
Zoznamy s poľom
Zoznam najčastejšie využíva toho, že hoci veľkosť poľa nemôžeme za behu programu meniť, môžeme za behu vytvoriť pole nové.
Zoznam je potom trieda, ktorá obsahuje
metódy pre pridanie a odstránenie prvkov (a mnoho ďalších,
pre nás teraz nepodstatných metód). Trieda v podstate obaľuje pole a
obsahuje navyše premennú, kde si uchováva počet
prvkov. Pri vytvorení inštancie sa vytvorí pole napr. O 12tich
prvkoch a premenná s počtom prvkov sa nastaví na 0
. Pri pridaní
prvého prvku sa prvok vloží na prvý index
v poli a počet prvkov sa inkrementuje. Takto môžeme pridať
až 12 prvkov, než polia naplníme. Vo chvíli, keď vyčerpáme
kapacitu poľa, jednoducho vytvoríme nové,
treba 2x väčší. Prvky zo starého poľa do neho
skopírujeme a staré polia zahodíme. Až sa toto nové pole
opäť naplní, budeme situáciu opakovať. Takýmto spôsobom naozaj interne
funguje kolekcie List
, s ktorou sme doteraz pracovali.
List
s poľom si môžeme predstaviť asi takto:
List
na obrázku má 8 prvkov. Prvky sú uložené v
internom poli, ktoré má prvkov 12. Posledné 4 prvky sa
nevyužívajú a List
sa zvonku tvári ako že tam nie sú.
Výhodou je rýchlosť prístupu k prvkom pomocou indexov vďaka využitiu poľa. Nevýhodou je samozrejme časové oneskorenie potrebná na vytvorenie nového poľa a prekopírovanie prvkov, aj keď nastáva len občas. Ďalšie, aj keď menej bolestivú nevýhodou je, že kolekcia zaberá v pamäti viac priestoru, než je nutné. Tento typ zoznamu je napriek tomu najpoužívanejší kolekcií v .NET a je pomerne dobre optimalizovaný.
List s poľom je teda v .NET zastúpený triedou List
a jeho
negenerické náprotivok je ArrayList
. Popíšme si dôležité
metódy na triede List
:
Metódy a ďalšie prvky na triede List
List implementuje rad interface najmä potom IList
. Ten tvorí
základ kolekcie a obsahuje nasledujúce metódy:
Add()
- Pridá nový prvok do listu.Clear()
- Vymaže všetky prvky.Contains()
- Vrátitrue
, ak list obsahuje daný prvok.CopyTo()
- Metódu už poznáme z poľa, umožňuje skopírovať prvky z listu do poľa.IndexOf()
- Vráti index prvého výskytu daného prvku v liste.Insert()
- Vloží na daný index nový prvok (a ďalšie prvky posunie).Remove()
- Vymaže daný prvok. Táto funkcia je veľmi užitočná v prípade, že máme vList
u inštancie nejakej triedy (napr. Používateľa), nemusíme si držať ich číselné indexy, len zavoláme napr.list.Remove(karel)
, kedy odovzdáme konkrétnu inštanciu, ktorá sa má zo zoznamu odobrať.RemoveAt()
- Vymaže prvok na danom indexe.
Hoci sme si List
vyskúšali už 1000krát, pre úplnosť si
predsa len ukážme niekoľko riadkov kódu:
{VBNET_CONSOLE}
Dim list As New List(Of Integer)()
list.Add(5)
list.Add(10)
Console.WriteLine("Prvý prvok: {0}", list(0))
{/VBNET_CONSOLE}
Výstup programu:
Konzolová aplikácia
Prvý prvok: 5
Kód vyššie vytvorí List
typu Integer
, pridá do
neho dve čísla a potom vypíše prvý prvok do konzoly. Pracujeme s indexy
akoby sme pracovali s poľom, ale môžeme do neho za behu programu pridávať
prvky a tiež je mazať.
Samotný List
ešte dodáva ďalšie metódy, popíšme si aj
tie:
AddRange()
- Pridá do listu prvky z odovzdaného poľa. Podobne môžeme volať aj metódyInsertRange()
aRemoveRange()
. Je dobrý nápad metódu využívať, keďže nám ušetrí cyklus. Jedinou záludnosťou je, že vie pridávať iba z poľa. Za chvíľu si ukážeme čo s tým.AsReadOnly()
- Vráti inštanciu listu, z ktorej možno prvky iba čítať. Vhodné pre zapuzdrenie prvkov kolekcie.Count
- Vlastnosť nesúci počet prvkov v liste. Všimnite si, že sa vlastnosť nevymenujeLength
(ako u pole), pretože dĺžka listu je o niečo väčší. Pravú dĺžku listu získame vlastnostíCapacity
, aj keď nám tento údaj asi k ničomu nie je.Find()
- Vyhľadá daný prvok pomocou predikátu (ktorý je, ako už vieme, delegátom). Je to veľmi jednoduché a efektívne, pretože môžeme použiť zápis cez lambda funkcie. Ukážme si, ako by sa na zozname typuList
dátového typuint
vyhľadalo číslo väčšie ako25
:
Dim list As New List(Of Integer)() list.Add(5) list.Add(10) list.Add(30) Dim cislo As Integer = list.Find(Function(a) a > 25) Console.WriteLine(cislo)
Výstup programu:
Konzolová aplikácia
30
Find()
vráti prvý nájdený prvok alebo predvolenú hodnotu
typu pri neúspechu (pri objektoch null).
FindAll()
- Podobne akoFind()
môžeme používať metóduFindAll()
, ktorá nájde všetky zodpovedajúce prvky a vráti novýList
, ktorý tieto nájdené prvky obsahuje:
Dim list As New List(Of Integer)() list.Add(5) list.Add(10) list.Add(30) list.Add(35) Dim cislaVetsiNez25 As List(Of Integer) = list.FindAll(Function(a) a > 25) For Each i As Integer In cislaVetsiNez25 Console.WriteLine(i) Next
Výstup programu:
Konzolová aplikácia
30
35
Vďaka delegátom a lambda výrazom je
všetko tak jednoduché. Ďalej list ponúka metódy FindIndex()
,
FindLast()
a FindLastIndex()
. Zaujímavá je ešte
metóda BinarySearch()
, ktorá vyhľadáva prvok rovnako ako
Find()
, ale je oveľa rýchlejší. Predpokladom je však fakt, že
je list zoradený. Viac pri algoritme binárne
vyhľadávanie
Exists()
- funguje podobne akoFind()
, iba nevracia nájdený prvok, aletrue
ak bol nejaký nájdený, inakfalse
.LastIndexOf()
- Obdoba metódyIndexOf()
, vracia index posledného výskytu daného prvku v liste.RemoveAll()
- Odstráni všetky prvky, ktoré zodpovedajú danému predikátu.Reverse()
- prevráti list tak, aby bol prvý prvok ako posledný a naopak posledný ako prvý.Sort()
- SetřídíList
. Je dôležité, aby jeho prvky obsahovali rozhraniaIComparable
, inak metóda vyvolá výnimku. Základné triedy a štruktúry z .NETIComparable
implementujú, u svojich tried ho vieme dodať.ToArray()
- Veľmi používaná metóda, ktorá vytvorí pole prvkov z listu a to vráti. Keďže pole je štandardná výmenná štruktúra v .NET, budeme metódu používať veľmi často. Všimnite si, že napr. MetódaAddRange()
berie v parametri poľa, nie list. To aby bola univerzálna. Ak teda chceme skopírovať prvky jedného listu do druhého, urobíme to takto:
list1.AddRange(list2.ToArray())
Až na niekoľko metód sme si popísali celý list.
Vyskúšajte si ďalšie metódy ako Sort()
, vyhľadávanie a
podobne. Detailnejšie prácu s kolekciami sa budeme ešte venovať, až sa
dostaneme k technológii LINQ
.
V budúcej lekcii, Spájať zoznam vo VB.NET , si uvedieme druhý typ listu, ktorým je spájať zoznam.
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é 6x (157.75 kB)
Aplikácia je vrátane zdrojových kódov v jazyku VB