Java programozás 14. – Tömbök

Tömbök, avagy de sokan vagytok!

A tömb, mint adattípus az összetett adattípusok közé tartozik. A tömb valójában egy sorszámozott egyforma típusú elemeket tartalmazó halmaz. Halmaz alatt csak annyit értek, hogy több elemet tartalmaz. A tömbök mérete (hogy hány elemet tartalmaz) középiskolai szinten lényegtelen, akkora tömbökkel nem dolgozunk, ami a túl nagy méret miatt problémát okozna. Ami viszont fontos: a tömb mérete csak egyszer adható meg, amikor deklaráljuk a tömböt. Vagyis ha megadtam, hogy ez egy 10 elemet tartalmazó tömb, akkor ezen később nem változtathatok. Különösen figyelni kell erre akkor, amikor nem tudod, hogy hány elemet szeretnél tárolni, akkor kénytelen vagy az elméleti maximális méretet beállítani, amit a feladat ad meg. A tömböt logikailag ugyanúgy kell deklarálni, mint egy egyszerű változót. Megadjuk a típusát és nevét.

int[] tomb;

A tömb deklarálás formailag ettől el is térhet, a következő alakok is használhatóak:

int []tomb;

vagy

int tomb[];

Én az első deklaráció típust használom, számomra így logikus. Ha felolvasnám az általam használt alakot, akkor így hangzana: ez egy egészeket tartalmazó tömb, melynek neve: tomb. Félkövérrel kiemeltem a fontos részeket, amelyek pont ilyen sorrendben szerepelnek a deklarációban.

Észrevehetted, hogy itt csak a tömb típusát és nevét adtam meg, de a méretét nem. Pedig azt írtam, hogy a tömbnek mérete is van, ami a megadása után nem változhat. A tömb méretének megadása megtörténhet közvetlenül a deklarációkor. Ezt akkor célszerű így használni, ha már ekkor tudod, hogy hány elemet szeretnél tárolni benne. Adott a következő feladat: Sorsolj ki 10 egész számot és tárold el őket. Ilyenkor azonnal megadható a tömb mérete is:

int[] tomb = new int[10];

Az is előfordulhat, hogy szükségem lesz egy egészeket tartalmazó tömbre, de még nem ismert számomra, hány darab elemet szeretnék tárolni. Jellemzően ez fájlbeolvasáskor fordul elő, esetleg kiválogatás, szétválogatás témakörben, melyeket majd később ismertetek. Ilyenkor a tömb deklarálása után tetszőleges programkódok lehetnek, melyek nem használják még a tömböt, nem is használhatják, hiszen nincs mérete. Maga a tömb már név szerint létezik, de még nem foglalt le neki a rendszer memóriát az elemek tárolásához. Ellenben a méret megadása előtt megszámolhatom, hogy majd mekkora tömbre lesz szükségem, és akkor állítom be a méretet, ha már biztosan tudom mekkorára van szükségem.

int[] tomb;
// ...
// ...
tomb = new int[10]

A tömbméretet mindenképpen azelőtt kell megadni, mielőtt használni szeretnénk. Fontos azt is tudni, hogy habár a tömb méretének megadásakor a tömbbe mi még nem helyeztünk el elemeket, a tömb nem üres. A méret megadásának kulcsa a new operátor. Ez létrehozza magát a tömb objektumot, ami a méretnek megfelelő darabszámú elemet képes tárolni, és aminek a rendszer azonnal lefoglalja a tároláshoz szükséges memóriaterületet. Ennek során a tömbben lévő minden elem kap egy kezdőértéket, amely a tömb típusától függ. A kezdőérték minden elemnél számok esetén 0, logikai típus esetén pedig false lesz. Később, ha mi magunk helyezünk el bárhová a tömbben egy értéket , csak az adott helyen lévő elem kezdő értékét írjuk át. A tömb new operátorral történő létrehozását – ezáltal kezdőértékekkel való feltöltését – inicializálásnak nevezzük.

Lássuk hogyan lehet egy tömböt használni.

Egy tömb, mint már említettem egy sorszámozott egyforma típusú elemeket tartalmazó halmaz. A sorszámozásnak fontos szerepe van, mert az elemek sorrendje – amíg meg nem változtatjuk – kötött. Mindenkinek megvan a saját azonosítója, amit nevezzünk indexnek. A sorszám annyiban nem a legpontosabb elnevezés, hogy itt a sorszámozás –  amit innentől nevezzünk indexelésnek – 0-val kezdődik. Ebből következik, hogy a legutolsó elem indexe mindig a tömbméret-1. Az indexek mindig pozitív egész számok!

Mivel minden tömbelem helye fix, és a helyét az elem indexe adja meg, ezért lehet egy tetszőleges elemre hivatkozni a következő módon:

tomb[index]

Ez az adott indexű helyen tárolt elem konkrét értékét adja vissza, és amíg direkt nem cserélgetjük össze az elemeket, vagy nem változtatjuk meg az értéküket, mindig ugyanazt az értéket adja. Így lehet például a tömb feltöltése közben az adott helyen lévő “tárolóban” értéket elhelyezni. Értelemszerűen az index legkisebb értéke 0 lehet (ez az első elem), a legnagyobb pedig tömbméret-1 (ez az utolsó). De hogyan tudjuk a tömbméretet megkapni? Az egy dolog, hogy mi adtuk meg a programban valahol, de már nem emlékszünk rá, vagy nem akarjuk mindenhova azt a konkrét számot beírni, mert lehet, hogy később átírjuk a tömb méretét. A tomb.length mindig megadja egy tetszőleges tömb méretét.

tomb[0] // mindig ez az első elem
tomb[tomb.length-1] // mindig ez az utolsó elem

Fontos, hogy nem a tömbben általunk eltárolt elemek számát adja meg, mert az lehet kevesebb is, mint a tömb mérete. Például tudom, hogy legfeljebb 20 értéket akarok tárolni, akkor egy 20 elemű tömbre van szükségem. És ha csak 15-öt tároltam el? Akkor az utolsó 5 üres lesz. Van ilyen. A tomb.length tehát azt a darabszámot adja meg, amennyi elem maximálisan elfér a tömbben és nem a már eltárolt elemek számát. Ha nem használtuk ki a tömb teljes méretét, akkor nekünk kell külön nyilvántartani, hogy melyik az utolsó elem, amit mi helyeztünk el a tömbben. Hiszen utána is vannak elemek a tömbben, a kezdőértékek. Az is lehet, hogy az általunk elhelyezett elem értéke 0, ami különbözik az utána következő 0 értéktől, ami már a kezdőérték miatt annyi! A lényeg: saját változóban tárold azt az indexet, ami annak az utolsó elemnek a helye a tömbben, amit te helyeztél el benne. Legyen ez a változó mondjuk db nevű.

tomb[db] // ez az utolsó általam elhelyezett elem
tomb[tomb.length-1] // ez pedig a tömb utolsó eleme, ami kezdőérték

Egyik kedvenc hibám, amit a diákoknál látok: tomb.lenght Ezt a hibát percekig lehet keresni. Hányszor futottam már bele ilyenbe. Tessék ügyelni a helyesírásra! Még ha nem is tanulsz angolt – ami az informatikában elég nagy hátrány – tanuld meg helyesen leírni az angol szavakat!

A feladat a következő: Töltsünk fel egy 10 elemű egészeket tartalmazó tömböt az [1;100] intervallumból és tároljuk el a kisorsolt értékeket. Amikor egy tömbbel dolgozunk, szinte mindig ciklusra van szükség. Hogy a ciklus milyen típusú (elöl tesztelő, hátul tesztelő vagy növekményes, esetleg speciális foreach), azt mindig az adott feladattípus dönti el. Amikor például egy tömböt feltöltünk értékekkel vagy ki akarjuk íratni a tartalmát, akkor úgyis végig kell nézni az egészet.

Mivel a ciklusokat már feltételezem, hogy ismeri az olvasó, így lássuk a megoldásokat alap feladatokra, egyelőre nem teljes programban. A lenti kódban a már ismertetett módon használom a számsorsolást:

for( int i = 0; i < tomb.length; i++ )
{
  tomb[i] = (int)(Math.random()*100)+1;
}

Ez a programrész egy tetszőleges méretű tömböt feltölt egy adott méretű intervallumból. A két kiemelt sor tartalmazza a lényege (a többi csak formaság). Az 1. sorban indítunk egy növekményes ciklust, ami egy ciklusváltozót (i) elindít 0-tól és addig megy amíg kisebb, mint a tomb nevű tömb mérete. Vagyis mi lesz az i utolsó értéke? Tömbméret-1. Ismerős? Ez az utolsó elem indexe. Vagyis ez a ciklus végiglépteti az i változót a tömb összes lehetséges indexén. Akármekkora is a tömb. Ezért kérdeztük meg a méretét tőle, mert lényegtelen, hogy a program elején mekkora tömbméretet adtunk meg. A 3. sorban pedig a léptetett indexeket felhasználva a tömb minden elemének egy véletlenszerű értéket adunk a megadott intervallumból. Apropó, ez melyik intervallum? … … … Számold ki!

Mi van akkor, ha ellenőrizni akarjuk, hogy a tömböt tényleg megfelelően töltöttük-e fel? Hátha elszúrtuk az intervallumot.

for( int i = 0; i < tomb.length; i++ )
{
  System.out.print(tomb[i]+" ");
}

Ezt a programrészt már nem is kell nagyon magyarázni. Az 1. sor ciklusa segítségével végigmegyünk a tömb összes indexén. A 3. sorban pedig mindig kiíratjuk a tömb aktuális indexű (vagyis mindegyik) elemét úgy, hogy egy szóközt is hagyunk utána, hogy az elemek elkülönüljenek egymástól.

Hogy néz ki ez az egész egyben?

public class Tombfeltoltes
{
  public static void main( String[] args )
  {
// tömb deklarálása és méretének megadása
    int[] tomb = new int[10];

// tömb feltöltése
    for( int i = 0; i < tomb.length; i++ )
    {
      tomb[i] = (int)(Math.random()*100)+1;
    }

// tömb elemeinek kiíratása
    for( int i = 0; i < tomb.length; i++ )
    {
      System.out.print(tomb[i]+" ");
    }
// extra sordobás
    System.out.println();
  }
}

Talán a 20. sor nem világos mit keres ott. Mivel a tömb elemeit egymás mellé írjuk le, ezért az utolsó elem után – vagyis a ciklus befejeztével – illik egy új sort kezdeni. Hátha jön még más feladat is, ami jó lenne ha elválna a kiíratástól.

Hamarosan bemutatom a tömbök komolyabb szintű kezelését is, de ehhez a fentieket készségszinten ismerni kell.

Következő lecke: String

5 Replies to “Java programozás 14. – Tömbök”

  1. Pingback: Java programozás 13. – Osztályok és objektumok

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük

*

Ez a weboldal az Akismet szolgáltatását használja a spam kiszűrésére. Tudjunk meg többet arról, hogyan dolgozzák fel a hozzászólásunk adatait..