05-A konténerek

Most felokosítjuk az előző fejezet kocsmáját! Lehet, hogy egy picit elvesztetted a fonalat, ha az előző fejezetet nem egy nekifutásban olvastad el. Igazából azért nem olyan sok dolgot csináltunk, csak mindent jól megmagyaráztam.

Ezt a programot hamarosan tovább okosítjuk, de először megismerünk egy remek eszközt arra, hogy sok egyforma dolgot könnyen tudjunk kezelni.

Mi az a konténer?

Eddig csak olyan dolgokat használtunk, amiket darabonként kezeltünk.

Például:

int a=42 // egy darab változó

Ember jane=new Ember("Jane",1); // egy darab objektum példány

Ez remek dolog akkor, ha előre tudjuk, hogy miből mennyi van, és ezek nem túl sokan vannak. De mondjuk egy 400 fős kocsmai partit nem szívesen szimulálnánk úgy, hogy egyesével kell létrehozni és itatni az embereket, ugye?

Vagy, vegyünk egy egyszerűbb példát! Milyen jó lenne, ha miután valaki kidőlt a kocsmában, kiírnánk, hogy ki miket ivott... De hova tegyük ezeket? Nem csinálhatunk nekik 10 változót, mert lehet, hogy valaki 11-et iszik. Valami olyan dologra lenne szükség, ami képes arra, hogy azonos dolgokból (például Innivaló példányok) bármennyit tárolni tudjon.

A C korában tömböket használtak erre, például öt számot így lehetett könnyen tárolni:

int lottoszamok[5] = {2, 53, 12, 63, 26};

A lottoszamok[0] kifejezés értéke a legelső szám, a 2, és így tovább. De ez nem igazán jó, mert előre kell tudni, hogy pontosan mennyi elemet fogunk tárolni. Ötös lottónál okés, mert ott mindig 5 számjegy van.

De az elfogyasztott italok tárolására ez a megoldás nagyon macerás, hiszen lehet hogy 0 italt, 1 italt, 2 italt, 42 italt fogyasztottunk.

Ezért itt az idő, hogy nyugdíjazzuk a tömböket.

Mi az a konténer?

Mi más lenne, mint a való életben használt konténer logikájának a koppintása? :)

Egy konténer ami dobozokat tartalmaz

Csak annyi a különbség, hogy a valós konténer mérete azért korlátozott, míg a számítógépen a konténerek méretének csak a memória szab határt.

Konténerből sok fajta van:

No nem kell megijedni, ezek azért elég egyszerű jószágok, csak azért van ennyi, mert a Java készítői igyekeztek mindenre gondolni! Arra is gondoltak, hogy ezeknek a konténereknek olyan alfajtái legyenek, amik különféle szempontok szerint vannak optimalizálva. Van például olyan List, ami az elemek gyors előkeresésére van optimalizálva, ez az ArrayList. Van olyan List, ami arra gyúrt, hogy az elemek közé gyorsan lehessen berakni egy új elemet, ez a LinkedList. De egyelőre mi nem vagyunk ennyire igényesek, így az ArrayList jó lesz mindenre!

Készíts egy új projektet, és bele egy osztály ListDemo névvel! Rittyentsd bele ezt a kódot:

public class ListDemo {

    public static void main(String[] args) {
        List<String> nevek=new ArrayList<String>();

        nevek.add("Szundi");
        nevek.add("Szende");
        nevek.add("Hapci");
        nevek.add("Morgó");

        System.out.println("Az álmos törpe:"+nevek.get(0));
        System.out.println("Összesen van ennyi törpe:"+nevek.size());
    }

}

Mások osztályainak az importálása

Hupsz, egy apróság: az ArrayList meg a List most alá van húzva. Azért, mert ezeket nem mi csináltuk, és nem része a projektnek. Ha fölé mész az aláhúzott ArrayList-re, rögtön felajánlja az Eclipse, hogy ő már látott valahol egy ArrayList osztályt, és azt importáljuk be. A beimportálás azt jelenti, hogy megmondjuk az általunk megírt osztálynak, hogy más osztályokat is használjon. (Eddig is csináltunk ilyet, hiszen a Kocsma is több osztályból készült. Azonban ott minden ugyanabban a projektben volt, ezért nem kellett ezzel foglalkozni.)

Nos, tehát két dolgot tehetsz: kattints rá a "jóvanaz, importájjad" sorra a felajánlott javítások közt.

Vagy pedig, használd a Ctrl+Shift+O billentyűkombinációt, és minden importálást elintéz magától. Ha tud. Jelen esetben van egy kis pittyputty, ugyanis List osztály igazából a Javahoz jár, mégpedig kétszer is - és meg kell mondani, hogy melyiket is akarod használni. A java.util.List a helyes választás a feljövő ablakból.

Ha sikerült megmondani hogy mit importálgasson, akkor azok automatikusan megjelennek az osztály programjának az elején így:

import java.util.ArrayList;
import java.util.List;

Vajon mennyi kész osztály jár a Javahoz? Többezer! Ne is akard megtanulni őket, amiket használni fogsz, ahhoz magadtól hozzászoksz!

Vissza a kódra

Ook, a nevek akkor az a konténer, igaz? Igaz! Ez is egy objektum. Mégpedig egy nagyon okos, általános fajta, aminek meg lehet adni, hogy miket fogsz tenni a konténerbe. Mi itt most Stringeket teszünk bele, ezért a kacsacsőr string. Ezt a kacsacsőrös dolgot nevezik úgy, hogy generics, és később ám nagyon fogjuk szeretni!

Aztán... aztán miért nem

List<String> nevek=new List<String>();

ahogy logikus lenne? Nos azért nem, mert a List önmagában még nem konténer, csak konténer fajta. Úgy képzeld el, hogy van egy ős List konténer, ami szinte semmit nem tud csinálni, és ebből származik az ArrayList (ami tud dolgokat tárolni, és könnyen előszedni) meg a LinkedList (ami dolgokat tárol, és gyorsan tud új elemet rakni a lista közepére), stb...

De akkor miért nem

ArrayList<String> nevek=new ArrayList<String>();

Nos, ez éppenséggel teljesen helyes. Csak egy pici szépséghibája van, mégpedig az, hogy kilóg a lóláb, mert innentől bárhova átadod a nevek konténert, ott pontosan meg kell adnod hogy ArrayList... No, és ha miután készen vagy, szeretnéd mégiscsak az ArrayList helyett a LinkedList-et használni, akkor mindenhol írhatod át... Ezért maradjunk annyiban, hogy érdemes úgy gondolkodni, hogy minél általánosabb típusú legyen a változó amit használunk, függetlenül attól hogy milyen leszármazott típust hozunk létre.

Kocsmául kifejezve:

// Mindegy, hogy sör vagy bor, ez csak egy Innivaló
Innivalo sor=new Sor();
Innivalo bor=new Bor();


// Mindegy, hogy épp mire gyúrtunk, ez csak egy List<String>
List<String> gyorsanKivesz=new ArrayList<String>();
List<String> gyorsanBerak=new LinkedList<String>();

Mi is volt még itt a kódban? A List konténer tartalmaz pár praktikus metódust:

nevek.add("Szundi"); // elem hozzárakása a lista végére
nevek.get(0); // elem előszedése sorszám alapján, a legelső a 0. elem, stb.
nevek.size(); // a konténerben található elemek száma

Autocomplete

Ne feledd, hogy a Ctrl+Space gombokkal bármikor hozzáférsz az autocomplete-hez. Azaz, nem kell fejben tartanod, hogy vajon a List-nek milyen metódusai vannak, csak pögyögd be hogy nevek. és a pont után nyomd meg a Ctrl+Space-t.

Feladat: Próbáld ki a progit, és tegyél bele még törpéket! Vajon mi történik, ha a maradék három törpét a println-ek után adod a listához?