A for-each ciklus

Sokszor feladat (a miénk is lesz) hogy a konténer minden elemét kiírassuk a képernyőre. Nos, mivel a List get() metódusa megad egy elemet, és mivel tudjuk, hogy az elemek 0-ás sorszámtól kezdődnek, és a legutolsó sorszám a size()-1, akkor rögtön kilogikázhatnák egy remek for-ciklust erre:

public class ListDemo {

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

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

        for (int i=0;i<nevek.size();i++) {
            System.out.println(nevek.get(i));
        }
    }
}

Őőő... ugye minden világos? Az i értékét tekerjük 0-tól, amíg nem éri el az utolsó elem indexét, és aztán a gettel kitúrjuk az egyes elemeket.

Ne így csináld!

Ez a modern programok legérzékenyebb pontja, ezért hamar felejtsük el!

Hogy miért veszélyes ez? Ó, elég egyetlen betűt elgépelni, és máris más történik. Például a gépeknek lehet, hogy logikus, hogy a legelső elem a nulladik, de az embereknek az első elem az 1-es.

for (int i=1;i<nevek.size();i++) {
    System.out.println(nevek.get(i));
}

Persze ez ki fogja hagyni a legelső elemet...

A helyes megoldás a for-each ciklus!

Diamond operator

Az igazán szemfülesek észrevettek egy csalást a konténer megadásnál: az ArrayList-en nem volt String paraméter. Ez egy egyszerűsítés, Java7 verziótól kezdve ki lehet hagyni a típusmegadást. Az így keletkezett két kacsacsőr erős képzelettel egy gyémántot formáz, ezt nevezik diamond-operatornak (azaz gyémánt-műveleti jelnek).

for-micsoda?

Az eddigi sima for ciklus lényege az volt, hogy valami változót növelgetett, és kész. A for-each jelentése "minden egyes", és arra használják, hogy egy konténer minden egyes elemén végigmenjünk. Anélkül hogy tudni kellene, hogy 0-ról kell kezdeni, meg túrkálni a konténerben a get-tel.

Valahogy így:

public class ListDemo {

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

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

        for (String nev:nevek) {
            System.out.println(nev);
        }
    }
}

Kicsit ízlelgessük ezt a for-ciklust. Igaziból semmi hagyományos for ciklusos dolog nincs benne, épp csak a kezdete. A for után egy változó deklaráció van, majd egy kettőspont, jajj, és egy konténer.

A dolgot úgy kell olvasni, hogy "for each nev in nevek" azaz minden egyes elemet a nevek-ből vegyen ki a nev változóba. Persze nem egyszerre, csak egymás után, végigmenve az egész konténeren:

for (String nev:nevek) {
    System.out.println(nev);
}

Mivel nincs kezdőérték, nincs végérték, nincs ciklusváltozó, ezért nem lehet mit elrontani benne.

Itt az idő, hogy nyugdíjazzuk a sima for ciklust - hiszen nagyon-nagyon ritkán fogjuk újra használni bármire.