Jelenlegi hely

21.1.1 A Collection interfész

A Collection az objektumok (elemek) csoportját tárolja.

public interface Collection<E> extends Iterable<E> {
    // Basic Operations
    int size();
    boolean isEmpty();
    boolean contains(Object element);
    boolean add(E element);         // Optional
    boolean remove(Object element); // Optional
    Iterator iterator();

    // Bulk Operations
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c); // Optional
    boolean removeAll(Collection<?> c);        // Optional
    boolean retainAll(Collection<?> c);        // Optional
    void clear(); // Optional

    // Array Operations
    Object[] toArray();
    <T> T[] toArray(T[] a);
}

Az interfésznek van metódusa, ami megmondja hány elem van a gyűjteményben (size, isEmpty), leellenőrzi, hogy az adott objektum benne van-e a gyűjteményben (contains), hogy hozzáadjon elemet gyűjteményhez vagy elvegye belőle (add, remove), bejárót (más néven iterátort) szolgáltat a bejáráshoz (iterator).

Az add metódus boolean visszatérési értéke azt jelzi, hogy történt-e a gyűjteményben változás. Ugyanis olyan implementáció esetén, ahol az elemek többszörös tárolása nem megengedett, nem történik változás, ha az elemet már eleve tartalmazta a gyűjtemény. Hasonlóan, a remove metódus esetén csak akkor változik a gyűjtemény állapota, ha benne volt az adott elem, és így sikeres volt a kivétel.

A gyűjtemények bejárása

Két módja van hogy bejárjuk a gyűjteményeket. Az egyik a for-each ciklussal, a másik az iterátorok használatával.

For-each ciklus

A for-each ciklus megengedi, hogy bejárjuk a gyűjteményt vagy tömböt a for ciklus használatával. A következő kód a for-each ciklust használja, és minden elemet külön sorban jelenít meg:

for (Object o : collection)
    System.out.println(o);

Iterátorok

Az iterátor egy olyan objektum, ami megengedi, hogy bejárjuk a gyűjteményt és eltávolítsuk az elemeket a gyűjteményből, ha akarjuk.

Az Iterator interfész:

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove(); // Optional
}

A hasNext metódus visszatérési értéke true, ha az iterációnak van még be nem járt eleme. A remove metódus eltávolítja a gyűjteményből az utolsó elemet, amit a next hívására kaptunk. A remove metódus a visszatérési értékével jelzi, hogy sikeres volt-e az eltávolítás.

Az Iterator.remove az egyetlen biztonságos út, hogy módosítsuk a gyűjteményt az iteráció folyamán. A viselkedés meghatározatlan, ha a gyűjtemény más egyéb úton módosítva lett, amíg az iteráció folyamatban volt.

Iterátor használata célszerű a for-each ciklus helyett a következő esetekben:

  • Törölni szeretnénk a bejárás közben.
  • Ki szeretnénk cserélni az elemeket.
  • Egyszerre többféle bejárásra is szükség van.

A következő metódus mutatja, hogyan használjuk az iterátort szűrőnek egy tetszőleges gyűjteményben (ezzel áttekintjük, hogy a gyűjtemény hogyan távolítja el a specifikus elemeket):

static void filter(Collection c) {
    for (Iterator i = c.iterator(); i.hasNext(); )
        if (!cond(i.next()))
            i.remove();
}

Ez az egyszerű kis kódrészlet sokoldalú, ami azt jelenti, hogy működik bármely gyűjteményben, kivétel nélkül minden implementációban. Ez a példa bemutatja, milyen könnyű sokoldalú algoritmust írni a Gyűjtemény keretrendszer segítségével.

A Collection interfész tömeges metódusai

A tömeges metódusok nem egy elemmel, hanem egész gyűjteménnyel hajtanak végre műveleteket. Implementálni lehet ezeket a metódusokat az alap metódusokat használva, bár a legtöbb esetben az ilyen implementációk kevésbé hatékonyak.

A tömeges metódusok

  • containsAll
    true a visszatérési értéke, ha a cél gyűjtemény tartalmaz minden elemet a meghatározott gyűjteményben (részhalmaz)
  • addAll
    Minden elemet hozzáad a meghatározott gyűjteményhez (unió)
  • removeAll
    Eltávolítja a célgyűjteményből az összes olyan elemet, amit a meghatározott gyűjtemény tartalmazott (különbség)
  • retainAll
    Eltávolítja a célgyűjteményből az összes olyan elemet, amit a meghatározott gyűjtemény nem tartalmazott. Azaz, csak azokat tartja meg a célgyűjteményben, amiket a meghatározott gyűjtemény is tartalmazott. (metszet)
  • clear
    Eltávolítja az összes elemet a gyűjteményből.

Az addAll, removeAll, és a retainAll metódus mindig true-val tér vissza, ha a célgyűjtemény módosítva volt a művelet végrehajtása alatt.

Egy egyszerű példa tömeges metódusok erejéről: a következő kifejezés eltávolítja az e elem minden példányát a c gyűjteményből:

c.removeAll(Collections.singleton(e));

Különösen praktikus, ha le akarjuk törölni az összes null elemet a gyűjteményből:

c.removeAll(Collections.singleton(null));

A kifejezés használja a Collections.singleton metódust, amelyik egy statikus gyártó metódus, ami visszaad egy olyan gyűjteményt, amely csak egy meghatározott elemet tartalmaz.

A Collection interfész tömb metódusai

A toArray metódusok olyanok, mint egy híd a gyűjtemények és a régebbi API-k között, amik tömböket várnak a bementen. A tömb metódusok lehetővé teszik, hogy a gyűjtemény tartalmát tömbként is elérhetővé tegyék. A paraméterek nélküli változat készíti el egy új Object tömböt. A bonyolultabb formája lehetővé teszi, hogy a hívó paraméterként egy tömböt adjon, és az eredmény is ilyen típusú tömb lesz.

Például, feltételezzük, hogy c egy gyűjtemény. Ekkor a következő metódus létrehoz egy tömböt, amelynek métere megegyezik a gyűjtemény méretével, elemei pedig a gyűjtemény elemei:

Object[] a = c.toArray();

Tegyük fel, hogy c ismert és csak sztringet tartalmaz (c típusa Collection<String>). Ekkor használható a következő változat is:

String[] a = c.toArray(new String[0]);