10. Tömbök

A tömb egy olyan változó, amely több azonos típusú adatot tartalmaz. A tömb (futásidei) hossza a létrehozásakor kerül megállapításra, és attól kezdve a tömb egy állandó méretű adatszerkezet.

Tömbök

A tömb egy eleme egyike a tömbben található tagoknak, mely a tömbben elfoglalt helye (indexe) alapján érhető el.

Ha különböző típusú adatokat akarunk tárolni egy szerkezeten belül, vagy olyan szerkezetre van szükség, melynek mérete dinamikusan módosítható, akkor használjunk a tömb helyett olyan gyűjtemény implementációkat, mint az ArrayList.

Fontos megjegyezni, hogy a tömbök objektumok, eltérően a C nyelvtől. Ez sok mindenben befolyásolja a működését.

10.1. Tömbök létrehozása és használata

Következzen az ArrayDemo nevű program, mely létrehoz egy tömböt, adatokkal tölti fel, majd kiírja tartalmát:

public class ArrayDemo {
    public static void main(String[] args) {
        int[] anArray;
        anArray = new int[10];
        for (int i = 0; i < anArray.length; i++) {
            anArray[i] = i;
            System.out.print(anArray[i] + " ");
        }
        System.out.println();
    }
}

A program kimenete:

0 1 2 3 4 5 6 7 8 9

Tömbök deklarálása

Ez a sor egy példaprogramból való, és egy tömb típusú változót deklarál:

int[] anArray;

Mint minden másfajta változó deklarálásakor, a tömb deklarálása is két részből áll: a tömb típusa és a tömb neve. A tömb típusa a tömb[] formátumban írható, ahol a típus a tömb által tartalmazott elemek típusa, a [] pedig azt jelzi, hogy tömbről van szó. A tömb minden eleme azonos típusú! A fenti példa int[] tömböt használ, tehát az anArray nevű tömb int típusú egészek tárolására lesz alkalmas. Néhány más típust tárolni képes tömb létrehozása:

float[] anArrayOfFloats;
boolean[] anArrayOfBooleans;
Object[] anArrayOfObjects;
String[] anArrayOfStrings;

Így is írható a deklaráció:

float anArrayOfFloats[];

Ez a forma nem ajánlott, mert a zárójelek jelzik, hogy tömbről van szó, így azok a típussal tartoznak össze, nem pedig a tömb nevével.

A tömb változók deklarálásával – mint bármely más nem primitív változóéval – sem jön létre tényleges tömb, és nem foglal le helyet a memóriában az elemek számára. A példakódban explicit módon kell létrehozni a tömböt és elnevezni anArray-nek.

Tömbök létrehozása

Tömb létrehozható explicit módon a Java new operátora segítségével. A példaprogram következő részében 10 egész tárolására szolgáló tömbhöz elegendő memóriát foglalunk le, és elnevezzük a már korábban deklarált anArray-nek.

anArray = new int[10];

Általában tömb létrehozásakor használni kell a new operátort, majd a tömb elemeinek típusát és végül a tömb méretét kell megadni szögletes zárójelek között:

new elemtípus[tömbméret];

Ha a new operátort kihagytuk volna a példaprogramból, a fordító leállt volna következő hibaüzenettel:

ArrayDemo.java:4: Variable anArray may not have been initialized.

Tömb kezdőérték beállítása

Használható a tömbök létrehozására és inicializálására a következő rövid formula:

boolean[] answers = {true, false, true, true, false};

Ilyekor a tömb nagyságát a {} közé írt elemek száma határozza meg.

Tömbelemek elérése

Most, hogy már megtörtént a memóriafoglalás a tömb számára, a program értékeket rendel a tömb elemeihez.

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

A kód ezen része azt mutatja be, hogy ahhoz, hogy hivatkozni tudjuk a tömb bármely elemére beírás vagy kiolvasás céljából, a tömb nevéhez egy []-et kell írni. A zárójelben (változó vagy egyéb kifejezés segítségével) írt érték az elérni kívánt tömbelem indexét jelöli.

Megjegyzés: A tömb (mivel objektum), tudja, hogy mekkora a mérete, és milyen index használható az indexelés során. Érvénytelen index esetén (a C nyelvvel szemben) a hiba futás közben egyértelműen kiderül: a futtatókörnyezetet egy ArrayIndexOutOfBoundsExeption típusú kivételt dob.

Tömb méretének meghatározása

A tömb méretének meghatározásához használható:

Tömbnév.length;

Figyelem! Azok, akiknek új a Java programnyelv, gyakran üres zárójelet raknak a length után. Ez nem működik, mert a length nem metódus! A length egy csak olvasható adattag, melyet a Java platform nyújt minden tömb számára.

A for ciklus a programunkban bejárja az anArray minden elemét, értéket adva nekik. A ciklus anArray.length–et használ a ciklus végének megállapításához.

10.2. Objektum tömbök

A tömbök tárolhatnak referencia típusú elemeket a primitív típusokhoz hasonlóan. Ezeket a tömböket is nagyrészt ugyanúgy kell létrehozni, mint a primitív típust tárolókat. A következő ArrayOfStringsDemo nevű program három String objektumot tárol, és kiírja őket kisbetűsítve.

public class ArrayOfStringsDemo {
    public static void main(String[] args) {
        String[] anArray = { "String One",
                             "String Two",
                             "String Three" };
        for (int i = 0; i < anArray.length; i++) {
            System.out.println(anArray[i].toLowerCase());
        }
    }
}

A program kimenete:

string one
string two
string three

A JDK 5.0–ás és későbbi verziói esetén lehetőség van a tömb elemeinek bejárásához egy újabb szintaktika alkalmazására. Ezt – más nyelvekben használt nevük alapján – for-each ciklusnak is szokás hívni. Figyelni kell azonban arra, hogy a ciklust ugyanúgy a for kulcsszó vezeti be, mint a hagyományos for ciklust.

String[] anArray = {"String One","String Two","String Three"};
for (String s : anArray) {
    System.out.println(s.toLowerCase());
}

A következő ArrayOfIntegersDemo nevű program feltölti a tömböt Integer objektumokkal.

public class ArrayOfIntegersDemo {
    public static void main(String[] args) {
        Integer[] anArray = new Integer[10];
        for (int i = 0; i < anArray.length; i++) {
            anArray[i] = new Integer(i);
            System.out.println(anArray[i]);
        }
    }
}

A program kimenete:

0
1
2
3
4

A következő programrészlet létrehoz egy tömböt, de nem rak bele semmit:

Integer[] anArray = new Integer[5];

Ez egy potenciális hibázási lehetőség, melyet az újdonsült Java programozók gyakran elkövetnek, amikor objektum tömböket használnak. Miután a fenti kódsor végrehajtódik, a tömb létrejött és képes 5 Integer objektum tárolására, bár a tömbnek még nincs eleme. Üres. A programnak explicit módon létre kell hoznia az objektumokat, és belerakni a tömbbe. Ez nyilvánvalónak tűnik, habár sok kezdő azt gondolja, fenti kódrészlet létrehozza az üres tömböt és még 5 üres objektumot is a tömbbe. Ha a tömbelemek létrehozása nélkül próbálunk azokra hivatkozni, akkor a futtatókörnyezetet NullPointerException-t fog dobni.

A probléma előfordulása még veszélyesebb, ha a tömb létrehozása a konstruktorban, vagy más kezdőérték állítással történik, és máshol használjuk a programban.

10.3. Tömbök tömbjei

Tömbök tartalmazhatnak tömböket. A következő példaprogram létrehoz egy tömböt, és kezdeti értékadásnál négy másodlagos tömböt, használ:

public class ArrayOfArraysDemo {
    public static void main(String[] args) {
        String[][] cartoons =
        {
            { "Flintstones", "Fred", "Wilma", "Pebbles", "Dino" },
            { "Rubbles", "Barney", "Betty", "Bam Bam" },
            { "Jetsons", "George", "Jane", "Elroy", "Judy", "Rosie", "Astro" },
            { "Scooby Doo Gang", "Scooby Doo", "Shaggy", "Velma", "Fred", "Daphne" }
        };
        for (int i = 0; i < cartoons.length; i++) {
            System.out.print(cartoons[i][0] + ": ");
            for (int j = 1; j < cartoons[i].length; j++) {
                System.out.print(cartoons[i][j] + " ");
            }
            System.out.println();
        }
    }
}

A program kimenetele:

Flintstones: Fred Wilma Pebbles Dino
Rubbles: Barney Betty Bam Bam
Jetsons: George Jane Elroy Judy Rosie Astro
Scooby Doo Gang: Scooby Doo Shaggy Velma Fred Daphne

Vegyük észre, hogy mindegyik másodlagos tömb különböző hosszúságú. A melléktömbök nevei cartoons[0], cartoons[1], és így tovább.

Mint az objektumok tömbjeinél, létre kell hoznunk a másodlagos tömböket a tömbön belül. Ha nem használunk kezdeti paraméterinicializálást, akkor a következőhöz hasonló kódot kell írnunk:

public class ArrayOfArraysDemo2 {
    public static void main(String[] args) {
        int[][] aMatrix = new int[4][];
        for (int i = 0; i < aMatrix.length; i++) {
            aMatrix[i] = new int[5];
            for (int j = 0; j < aMatrix[i].length; j++) {
                aMatrix[i][j] = i + j;
            }
        }
        for (int i = 0; i < aMatrix.length; i++) {
            for (int j = 0; j < aMatrix[i].length; j++) {
                System.out.print(aMatrix[i][j] + " ");
            }
            System.out.println();
        }
    }
}

A program kimenetele:

0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7

Meg kell adni a tömb hosszúságát, amikor létrehozzuk. Tehát egy tömbnek, ami tartalmaz másodlagos tömböket, meg kell adni a hosszúságát, amikor létrehozzuk, de nem kell megadni a másodlagos tömbök hosszúságát is.

10.4. Tömbök másolása

Használhatjuk a System osztály arraycopy metódust, hogy adatokat másoljunk hatékonyan egyik tömbből a másikba. Az arraycopy metódus öt paramétert vár:

public static void arraycopy(Object source, int srcIndex, Object dest, int destIndex, int length)

A két Object paraméter rámutat a kiinduló és a cél tömbre. A három int paraméter jelzi a kezdő helyet a forrás és a céltömbön belül, és az elemek számát, amennyit másolni akarunk.

A következő kép illusztrálja, hogyan megy végbe a másolás:

Tömb másolása

A következő ArrayCopyDemo program használja az arraycopy metódust, ami az elemeket a copyFrom tömbből a copyTo tömbbe másolja.

public class ArrayCopyDemo {
    public static void main(String[] args) {
        char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e', 'i', 'n', 'a', 't', 'e', 'd' };
        char[] copyTo = new char[7];
        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        System.out.println(new String(copyTo));
    }
}

A program kimenetele:

caffein

A következő képen lehet látni az arraycopy metódus működését:

arraycopy

Az eredménytömböt létre kell hozni, mielőtt meghívódik az arraycopy metódus, és elég nagyméretűnek kell lennie, hogy beleférjenek a másolandó tömb elemei.

Tömbkezeléshez további szolgáltatásokat nyújt a java.util.Arrays osztály is.

10.5. Ellenőrző kérdések

  • Mi a tömb?
  • Mi lehet Javában egy tömb elemtípusa?
  • Mit jelent az, hogy Javában a tömböt tömbreferenciával érhetjük el?
  • Mit tárol a tömb length példányváltozója?
  • Mit jelent, hogy egy tömb objektum-referenciákat tárol?
  • Mit jelent a többdimenziós tömb?

Melyik fordul le?

  • String temp [] = new String {"j" "a" "z"};
  • String temp [] = { "j " " b" "c"};
  • String temp = {"a", "b", "c"};
  • String temp [] = {"a", "b", "c"};

Hogyan tudhatjuk meg a myarray tömb méretét?

  • myarray.length();
  • myarray.length;
  • myarray.size
  • myarray.size();