Groovy verwendet die Listen aus Java, also das Interface java.util.List und die Implementierungen davon wie ArrayList. Groovy verzichtet aber in der Regel auf die Typisierung der Listen, die man in Java extra noch eingeführt hatte. Echte Erleichterung ist eine Kurzschreibweise, die es erlaubt, Listen im Programmcode einfach aufzubauen.
Die Initialisierung von Listen in Groovy
Die Kurzschreibweise zum Erstellen eines List-Objekts in Groovy sieht so aus:
def numbers = [1, 2, 3] def some_strings = ["foo", "bar"]
In Java gibt es keine gute Möglichkeit, ähnlich klar zu einer Liste zu kommen. Man müsste in Java schon so etwas aufbauen:
List some_strings = new ArrayList(); some_strings.add("foo"); some_strings.add("bar");
Es gibt noch ein paar Tricks, die das in Java etwas kürzer machen, aber alle sind nicht wirklich schön. Ich will sie deshalb hier auch gar nicht erst vorstellen.
Listentypen aus Groovy-Sicht
Wie eingangs schon gesagt: Groovy verwendet das Interface java.util.List und Listentypen wie java.util.ArrayList. Daran hat Groovy nicht gedreht. Aber die Möglichkeit der direkten Initialisierung ist neu.
Schauen wir uns einmal an, was Groovy aus der Listeninitialisierung macht:
def numbers = [1, 2, 3] print numbers.class
Die Ausgabe lautet
class java.util.ArrayList
Groovy erzeugt also eine ArrayList.
Nun gibt es abseits der ArrayList ja noch andere Listentypen in Java. ArrayList ist nur die einfachste und häufigste. Andere Möglichkeiten wären LinkedList, Stack oder Vector. Groovy erlaubt es daher in der Listeninitialisierung, den Typ der Liste anzugeben. Das geht so:
def numbers = [1, 2, 3] as LinkedList print numbers.class
Jetzt erhalten wir:
class java.util.LinkedList
gemischte Listen
Wie in Java können Listen Elemente verschiedenster Typen aufnehmen, auch gemischt:
def gemischtwarenladen = [1, "a", true]
Zugriff auf die Elemente einer Liste
Um an die Elemente einer Liste zu kommen, gibt es verschiedene Möglichkeiten.
Zunächst einmal geht natürlich weiterhin die getAt-Methode aus Java:
def some_strings = ["foo", "bar", "hello", "world"] print some_strings.getAt(2)
Mit dem Resulat „hello“. Der Grund ist: das nullte Element der Liste ist „foo“. So wie Java – und wie überhaupt die meisten Programmiersprachen – zählt Groovy die Liste angefangen mit dem nullten Element. Und wenn „foo“ das nullte Element ist, dann ist „hello“ das zweite. Das hat alles so seinen Sinn (glaub mir!), aber es bleibt ein beliebter Anfängerfehler.
Weitere Wege (die in Java so nicht gehen) sind:
Eckige Klammern:
def some_strings = ["foo", "bar", "hello", "world"] print some_strings[2]
Hier funktionieren auch negative Zahlen. (Das ist wohl by Python abgeschrieben, denn dort geht das auch). Die -1 indiziert das letzte Element der Liste. Die -2 das vorletzte.
def some_strings = ["foo", "bar", "hello", "world"] print some_strings[-1]
Die Ausgabe ist „world“.
Das geht auch mit -1 bis -4. Bei -5 erhalten wir diese Fehlermeldung:
Exception thrown
java.lang.ArrayIndexOutOfBoundsException: Negative array index [-5] too large for array size 4
weitere Elemente zur Liste hinzufügen
Nun kann man mit Listen natürlich auch arbeiten. Mal angenommen, wir wollen einen weiteren String zu unserer Sammlung hinzufügen:
def some_strings = ["foo", "bar", "hello", "world"] some_strings.add("more") print some_strings
Die Ausgabe lautet:
[foo, bar, hello, world, more]
Über Java hinaus kann man das aber auch so schreiben:
def some_strings = ["foo", "bar", "hello", "world"] some_strings << "more" print some_strings
Dieser Operator betrachtet (in Anlehnung an eine Stream-Syntax aus C++) das Array als einen Stream, in den man auf diese Art ein Element hineinschieben kann.
Was man sonst noch mit Listen machen kann
Groovy-Listen sind Java-Listen und können alles, was eine Java-Liste auch kann. Hier sind ein paar gängige Methoden. Achtung: die Liste ist nicht vollständig. Allein schon die Java-Liste kann noch einges mehr. Dafür möchte ich dann aber auf die offizielle Dokumentation der java.util.List verweisen.
add() | fügt ein neues Element hinzu |
contains() | prüft, ob die Liste das angegebene Element enthält. Liefert true, falls das der Fall ist und false, falls nicht. |
get() | Zugriff auf ein bestimmtes Element |
isEmpty() | liefert true, falls die Liste leer ist. Und false, falls die Liste mindestens ein Element enthält |
minus() | Liefert eine neue Liste zurück die aus der ursprünglichen Liste nur noch diejenigen enthält, die abgezogen wurden |
plus() | liefert eine neue Liste zurück, die die Elemente beider Listen enthält |
pop() | entfernt das letzte Element aus der Liste |
remove() | entfernt das Element an der benannten Position aus der Liste |
reverse() | liefert eine neue Liste zurück, die genau anders herum sortiert ist |
size() | liefert die Anzahl der Elemente aus der Liste zurück |
sort() | liefert eine neue Liste zurück, die sortiert ist |
Achtung: wenn es hier wiederholt heißt „liefert eine neue Liste zurück“, dann ist das genau so gemeint. Diese Methoden verändern die ursprüngliche Liste nicht. Ein Beispiel:
def some_strings = ["foo", "bar", "hello", "world"] println some_strings.reverse() println some_strings
Die zwei Zeilen der Ausgabe lauten:
[world, hello, bar, foo]
[foo, bar, hello, world]
Bitte nimm dir genug Zeit, diesen Unterschied zu verstehen.
Mehr Groovy gibt es hier.