Fast jedes Java-Programm verwendet sie extensiv, und trotzdem werden sie von der Sprache Java in keiner Weise unterstützt: Listen und Maps. Dementsprechend umständlich ist ihre Verwendung, und Programme, die mit diesen Datentypen arbeiten, werden schnell unübersichtlich. Groovy enthält einige syntaktische Erweiterungen, die es Ihnen ermöglichen, mit solchen Container in einer einfacheren und natürlicheren Weise umzugehen. Dabei wird insbesondere das Anlegen und initiale Füllen von Liste und Maps erleichtert und man kann in einer Array-ähnlichen Weise auf die Elemente zugreifen. Außerdem stellt Groovy einen eigenen Listentyp namens Range zur Verfügung, mit dem sich sehr einfach Wertebereiche durch die Angabe der Unter- und Obergrenze abbilden lassen. Groovy kennt keine typisierten Container, wie es sie in Java seit der Version 1.5 gibt, allerdings fällt dies nicht so stark ins Gewicht, da man in Groovy ohnehin eher mit untypisierten Werten arbeitet und Typecasts in der Regel nicht notwendig sind.

Listen in Groovy Bearbeiten

Listen sind in Groovy alle Typen, die das Interface java.util.List implementieren. Ein Teil der für Listen verfügbaren Methoden und Operationen kann allerdings auch auf Objekte angewendet werden, die nicht List, sondern nur das allgemeinere Interface java.util.Collection (für abstrakte, ungeordnete Behältertypen) implementieren.

Listen anlegen Bearbeiten

Sie können eine neue Liste anlegen, indem Sie einfach die darin enthaltenen Elemente in eckige Klammern eingeschlossen und durch Kommas getrennt aufführen.

groovy> liste = [1, 7.5, 'zwei Worte']
groovy> println liste.dump()
groovy> liste.each { println it }
<java.util.ArrayList@40af55f6 elementData={1, 7.5, "zwei Worte"} size=3 modCount=3></nowiki>
1
7.5
zwei Worte

Die Variable liste verweist also auf eine neue Instanz vom Typ java.util.ArrayList, die durch diese Art von Konstruktor standardmäßig erzeugt wird. Durch implizite oder explizite Typanpassung können Sie daraus auch ein Array machen (wobei in diesem Fall die Liste natürlich »typenrein« sein oder zumindest aus anpassbaren Typen bestehen muss.

groovy> def array1 = ['eins','zwei','drei'] as String[]
groovy> println array1.class.canonicalName
java.lang.String[]
groovy> int[] array2 = [1,2,3]
groovy> println array2.class.canonicalName
int[]

Wenn Sie einen anderen Listentyp ‒ oder sogar einen ganz anderen Collection-Typ ‒ mit Werten initialisieren wollen, rufen Sie einfach dessen Konstruktor auf und geben ihm eine Liste als Argument mit.

groovy> def set = new HashSet([1, 7.5, 'zwei Worte'])
groovy> println set.class.canonicalName
java.util.HashSet

Eine leere Liste definieren Sie einfach durch eine öffnende und eine schließende eckige Klammer ohne Inhalt.

groovy> def leereListe = []
groovy> println leereListe.size()
0

Die Elemente einer Liste können natürlich auch wiederum Listen sein. Auf diese Weise können Sie auch verschachtelte Listenstrukturen bauen.

groovy> verschachtelteListe = [['alpha','beta'],['gamma','delta']]
groovy> println verschachtelteListe.size()
2

Operatoren für Listen Bearbeiten

Verschiedene Operatoren sind für den Typ List (teilweise auch bereits für Collection) überladen, sodass sie eine besondere Bedeutung haben.

Mit dem Indexoperator können Sie auf einzelne Elemente oder Gruppen von Elementen einer Liste zugreifen, als wäre es ein Array. Allerdings ist auch hier einiges mehr möglich als bei einem Array in Java.

groovy> liste = ['alpha','beta','gamma','delta']
groovy> println liste[1]
beta
groovy> println liste[-2] // Negativer Index zählt von hinten
gamma
groovy> println liste[0,2,3] // Bildet neue Liste mit ausgewählten Elementen
["alpha", "gamma", "delta"]
groovy> println liste[0..2] // Zugriff auf Bereich von Elementen
["alpha", "beta", "gamma"]
groovy> println liste[2..0] // Abwärts zählender Bereich
["gamma", "beta", "alpha"]
groovy> println liste[1..-1] // Mit negativer Bereichsgrenze
["beta", "gamma", "delta"]

Das Gleiche ist natürlich auch schreibend möglich. Wenn Sie in ein Element schreiben, dessen Index noch nicht existiert, wird die Liste automatisch verlängert und mit null-Elementen aufgefüllt.

groovy> liste = ['alpha','beta','gamma','delta']
groovy> liste[0] = 'ALPHA'
groovy> println liste
["ALPHA", "beta", "gamma", "delta"]
groovy> liste[1,3] = 'BETA','GAMMA','DELTA' // Einen Teilbereich ersetzen
groovy> println liste
["ALPHA", "BETA", "GAMMA", "DELTA"]
groovy> liste[6] = 'ETA' // Liste wird bei Bedarf verlängert
groovy> println liste
["ALPHA", "BETA", "GAMMA", "DELTA", null, null, "ETA"]

Die folgenden »arithmetischen« Operatoren liefern jeweils eine neue ArrayList-Instanz.

groovy> liste = ['alpha','beta','gamma','delta']
groovy> println liste + 'epsilon' // Listenelement hinzufügen
["alpha", "beta", "gamma", "delta", "epsilon"]
groovy> println liste + ['epsilon','zeta'] // Liste hinzufügen
["alpha", "beta", "gamma", "delta", "epsilon", "zeta"]
groovy> println liste - 'beta' // Listenelement entfernen
["alpha", "gamma", "delta"]
groovy> println liste - ['alpha','delta'] // Elemente einer Liste entfernen
["beta", "gamma"]
groovy> println liste * 2 // Liste vervielfachen
["alpha", "beta", "gamma", "delta", "alpha", "beta", "gamma", "delta"]

Der Linksverschiebungsoperator (<<) hat fast dieselbe Wirkung wie der Plus-Operator (+), jedoch wird das Argument dem aktuellen Objekt hinzugefügt und keine neue Liste erzeugt.

groovy> liste = ['alpha','beta','gamma','delta']
groovy> liste << 'epsilon' // Listenelement hinzufügen
groovy> println liste
["alpha", "beta", "gamma", "delta", "epsilon"]

Ein weiterer Unterschied zwischen + und << zeigt sich, wenn eine Liste hinzugefügt wird: Der +-Operator hängt die zweite Liste an, während << die Liste selbst als Element hinzufügt:

groovy> println (['a', 'b' ] + [1, 2])
['a', 'b', 1, 2]
groovy> println (['a', 'b' ] << [1, 2])
['a', 'b' , [1, 2]]

Vordefinierte Methoden Bearbeiten

Des Weiteren enthält die Groovy-Laufzeitbibliothek eine Reihe vordefinierter Methoden für Listen bzw. Collections, die die ohnehin umfangreiche Standard-API für diese Typen noch einmal erheblich ausweitet und vor allem um Funktionalitäten erweitert, die für Groovy charakteristisch sind. Einige dieser vordefinierten Methoden, die sich auf die Abarbeitung aller Listen in einer Reihenfolge beziehen, haben wir uns schon weiter oben unter »vordefinierte Methoden« angesehen.

Die Methode pop() entfernt wie bei einem Stack das letzte Element aus der Liste und liefert es als Ergebnis zurück.

groovy> liste = ['alpha','beta','gamma','delta']
groovy> println liste.pop()
delta
groovy> println liste
["alpha", "beta", "gamma"]

Die Methode reverse() liefert eine neue Liste mit allen Elementen in umgekehrter Reihenfolge und lässt das Original unverändert.

groovy> liste = ['alpha','beta','gamma','delta']
groovy> println liste.reverse()
["delta", "gamma", "beta", "alpha"]

Die Methode flatten() löst eine verschachtelte Liste zu einer einzigen flachen Liste auf und liefert diese als neues Objekt zurück, ohne das Original zu verändern.

groovy> liste = [['alpha','beta'],['gamma','delta']]
groovy> println liste.flatten()
["alpha", "beta", "gamma", "delta"]

Die Methode count() stellt fest, wie oft der angegebene Wert in der aktuellen Liste vorkommt.

groovy> liste = ['alpha','beta','gamma','alpha']
groovy> println liste.count('alpha')
2

Die Methoden min() und max() suchen das kleinste bzw. größte Objekt in der Liste. Optional können Sie als Argument einen Comparator angeben oder eine Closure, die zwei Argumente vergleicht; in Groovy ist die zweite Form sicherlich die näher liegende. Bei einer leeren Liste ist das Ergebnis null.

groovy> liste = ['gamma','delta','BETA','alpha']
groovy> println liste.min()
BETA
groovy> println liste.min { a,b -> a.compareToIgnoreCase(b) }
alpha

Nach demselben Prinzip funktioniert die Methode sort(). Sie erzeugt eine neue Liste, in der Elemente sortiert sind. Als Sortierkriterium können Sie auch hier einen Comparator oder eine Closure angeben. Das Original der Liste wird dabei nicht verändert.

groovy> liste = ['gamma','delta','BETA','alpha']
groovy> liste.sort()
groovy> println liste
["BETA", "alpha", "gamma", "delta"]
groovy> liste.sort { a,b -> a.compareToIgnoreCase(b) }
groovy> println liste
["alpha", "BETA", "gamma", "delta"]

Ähnlich ist auch die Methode unique(), die doppelte Elemente entfernt. Hier kann optional ein Comparator oder eine Closure entscheiden, ob zwei Elemente als gleich anzusehen sind.

groovy> liste = ['alpha','beta','alpha','BETA']
groovy> liste.unique()
groovy> println liste
["alpha", "beta", "BETA"]
groovy> liste.unique { a,b -> a.compareToIgnoreCase(b) }
groovy> println liste
["alpha", "beta"]

Mit Hilfe der Methode join() können Sie alle Elemente einer Liste zu einem einzigen String verknüpfen. Das übergebene Argument wird dabei zwischen den Elementen eingefügt.

groovy> liste = ['alpha','beta','gamma','delta']
groovy> println liste.join(', ')
alpha, beta, gamma, delta

Die Methode groupBy() dient dazu, die Elemente einer Liste zu gruppieren. Sie liefert eine Map zurück, deren Schlüssel die Gruppierungskriterien und deren Werte jeweils eine Liste mit den zugehörigen Listenelementen enthalten. Eine Closure liefert jeweils das Gruppierungskriterium.

In dem folgenden Beispiel werden die in der Liste enthaltenen Werte nach den Anfangsbuchstaben gruppiert.

groovy> liste = ['Aluminium','Beryllium','Bismut','Blei','Cadmium','Chrom','Eisen']
groovy> gruppierung = liste.groupBy{it[0]}
groovy> for (x in gruppierung) { println "$x.key = $x.value" }
A = ["Aluminium"]
C = ["Cadmium", "Chrom"]
B = ["Beryllium", "Bismut", "Blei"]
E = ["Eisen"]

Die Methode inject() ruft eine Closure für alle Elemente der Liste auf. Dabei wird als zweites Argument beim ersten Durchlauf ein als Argument für inject() angegebener Anfangswert übergeben und in allen weiteren Durchläufen das Ergebnis des vorherigen Durchlaufs. Das Ergebnis des letzten Durchlaufs ist dann das Ergebnis des inject()-Aufrufs.

Diese Methode eignet sich beispielsweise für statistische Auswertungen. Das folgende Beispiel berechnet die Summe aller Werte in einer Liste.

groovy> werte = [1,7,5,2,9]
groovy> println werte.inject(0) { w, x -> w + x}
24

Im konkreten Fall könnte man dies allerdings auch einfacher mit der sum()-Methode haben. Sie summiert alle Elemente; dabei wendet sie die plus()-Methode an. Das Ergebnis ist also dasselbe, als würden Sie aus der Liste einen Ausdruck bilden, bei dem alle Elemente durch +-Zeichen verknüpft sind. Der Ergebnistyp bleibt dabei entsprechend erhalten. Optional können Sie eine Closure übergeben; in diesem Fall wird nicht die Closure summiert, sondern die Summe der Closure-Ergebnisse.

groovy> println ([1,2,3].sum())
6
groovy> println ([1,2,3.0].sum())
6.0
groovy> println (['A','B','C'].sum())
ABC
groovy> println (['A','B','C'].sum {it.toLowerCase()}
abc

Hier ist mir die Abgrenzung zum Kapitel "Vordefinierte Methoden zur Iteration über Objektmengen" nicht ganz klar, z.B. hätte ich inject() auch schon darin beschrieben.

Wertebereiche Bearbeiten

Relativ häufig hat man in der Programmierung mit einer Reihe von Daten zu tun, die sich durch eine Ober- und eine Untergrenze beschreiben lässt. Die enthaltenen Daten haben immer den Abstand 1. Typischerweise durchläuft man sie in einer Schleife oder man prüft, ob ein Wert in der so definierten Menge enthalten ist. Groovy hat dafür einen eigenen Datentyp, der auch durch die Sprache direkt unterstützt wird: der Wertebereich (Range). Ein geschlossener Wertebereich, das beide Grenzen enthält, beschreiben Sie durch die Unter- und Obergrenze, die durch zwei Punkte (..), die den Range-Operator bilden, verbunden sind. Bei einem rechtsoffenen Wertebereich, bei dem der rechte Wert nicht enthalten ist, steht vor dem rechten Wert zusätzlich ein Kleiner-Zeichen (<). Die Wertebereiche können aufwärts und abwärts verlaufen. Wenn bei einem geschlossenen Wertebereich Ober- und Untergrenze gleich sind, enthält das Wertebereich nur diesen einen Wert.

groovy> geschlossen = 1..3
groovy> geschlossen.each { println it }
1
2
3
groovy> rechtsoffen = 1..<3
groovy> rechtsoffen.each { println it }
1
2
groovy> abwärts = 3..1
groovy> abwärts.each { println it }
3
2
1
groovy> einWert = 2..2
groovy> einWert.each { println it }
2

Daran, dass wir in den Beispielen die each()-Methode an ihnen aufrufen, erkennen Sie bereits, dass es sich bei den Groovy-Wertebereichen um iterierbare Objekte handeln muss. Alle Wertebereiche implementieren das Interface Range, und dieses wiederum ist eine Erweiterung des Interface List.

Wertebereiche können aus allen Typen gebildet werden, die sinnvolle Implementierungen für die Methoden next(), previous() und compareTo() bieten. Sie können sich also ohne Weiteres selbst einen Typ bauen, aus dem sich Wertebereiche bilden lassen. Die Groovy-Standardbibliothek enthält bereits Wertebereiche für verschiedene Typen. Ober- und Untergrenze sollten vom selben Typ sein. Hier einige Beispiele ‒ beachten Sie, dass wegen der niedrigen Priorität des Range-Operators die Wertebereichausdrücke häufig eingeklammert werden müssen.

groovy> println 'aaa'..'aac' // String-Wertebereich
[aaa, aab, aac]
groovy> println 1.1 .. 5.1 // BigDecimal-Wertebereich
[1.1, 2.1, 3.1, 4.1, 5.1]
groovy> date = new Date()
groovy> println date .. (date+2) // java.util.Date-Wertebereich
[Tue Jan 09 22:38:27 CET 2007, Wed Jan 10 22:38:27 CET 2007, Thu Jan 11 22:38:27 CET 2007]
groovy> sqldate = new java.sql.Date(date.time) // java.sql.Date-Wertebereich
groovy> println (sqldate .. (sqldate+2))
[2007-01-09, 2007-01-10, 2007-01-11]
groovy> enum E { ALPHA, BETA, GAMMA, DELTA }
groovy> import static E.* 
groovy> println ALPHA..GAMMA // Enum-Wertebereich
[ALPHA, BETA, GAMMA]

Ein häufiger Anwendungsfall für Wertebereiche ist der Ersatz der konventionellen for-Schleife von Java:

groovy> for (i in 1..5) { println i }

Da ein Wertebereich ein normales Objekt ist, können Sie natürlich auch auf seine Properties und Methoden zugreifen. Allerdings können die Properties nur gelesen werden, da das Wertebereich ein immutabler Typ ist.

groovy> w = 1.1 .. 5.1
groovy> println w.from
1.1
groovy> println w.to
5.1

Im Allgemeinen können Wertebereiche aus abzählbaren Typen, z.B. 1..3 oder 'a'..<'b', genau wie unveränderliche Listen behandelt werden. Beachten Sie, dass der Wertebereich, obwohl der nur durch seine Grenzen definiert ist, nur Werte im ganzzahligen Abstand von dem links stehenden Grenzwert enthält

groovy> w = (1.3 .. 3.5)
groovy> println w.contains(2.3)
groovy> println w.contains(2.5)
true
false

Maps in Groovy Bearbeiten

Der letzte Datentyp, den Groovy durch spezielle syntaktische Leckereien unterstützt, ist die Map. Wie bei Listen gibt es auch hier wieder spezielle Operatoren zum Anlegen neuer Objekte und für den bequemen Zugriff auf die Elemente, und die Groovy-Standardbibliotheken halten verschiedene vordefinierte Methoden bereit.

Maps anlegen Bearbeiten

Eine Map legen Sie an, indem Sie Schlüssel-Wert-Paare, durch Komma getrennt, zwischen eckigen Klammern ([]) auflisten. Zwischen dem Schlüssel und dem Wert muss dabei jeweils ein Doppelpunkt (:) stehen. Erzeugt wird dabei eine Instanz der Klasse java.util.HashMap.

groovy> richtungen = ['n':'Nord','s':'Süd','o':'Ost','w':'West']
groovy> println richtungen
["o":"Ost", "n":"Nord", "w":"West", "s":"Süd"]

Eine leere Map erzeugen sie, indem Sie einfach einen Doppelpunkt zwischen eckigen Klammern schreiben.

groovy> leereMap = [:]
groovy> println leereMap.dump()
<java.util.HashMap@0 table={null} size=0 threshold=0 loadFactor=0.75 modCount=0 entrySet=[] keySet=null values=null>

Wenn Sie als Schlüsselwert vor dem Doppelpunkt ein den Groovy-Namensregeln entsprechendes Wort angeben, wird dieses als String-Konstante und nicht als Variablenname angesehen. Das hat den Vorteil, dass Sie sich in den häufigen Fällen, in denen Strings die Schlüssel einer Map bilden, einfach die die Anführungszeichen sparen können. Das obige Beispiel funktioniert also auch so:

groovy> richtungen = [n:'Nord',s:'Süd',o:'Ost',w:'West']
groovy> println richtungen
["o":"Ost", "n":"Nord", "w":"West", "s":"Süd"]

Der Nachteil ist, dass Sie in dem Fall, dass Sie nun tatsächlich Variablen als Schlüsselwerte verwenden möchten, diese erst in Ausdrücke umwandeln müssen, denn Ausdrücke, die nicht nur Variablennamen sind, werden als Schlüsselwerte akzeptiert. Schließen Sie in diesem Fall den Variablennamen einfach in runde Klammern ein, und schon werden die Variablen zu Ausdrücken.

groovy> var1 = 'n'; var2='s'; var3='o'; var4='w'
groovy> richtungen = [(var1):'Nord',(var2):'Süd',(var3):'Ost',(var4):'West']
groovy> println richtungen
["o":"Ost", "n":"Nord", "w":"West", "s":"Süd"]

Groovy erzeugt aus diesen speziellen Operatoren standardmäßige Instanzen der Klasse java.util.HashMap. Wenn Sie einen anderen Map-Typ benötigen, verwenden Sie einfach die HashMap als Argument für den Konstruktor.

groovy> linkedMap = new LinkedHashMap([n:'Nord',s:'Süd',o:'Ost',w:'West'])
groovy> println linkedMap.getClass().name
java.util.LinkedHashMap

Auf Map-Elemente zugreifen Bearbeiten

Die folgenden Operatoren und Methoden gelten für alle Klassen, die java.util.Map implementieren sowie für alle von java.util.Hashtable abgeleiteten Klassen.

Groovy ermöglicht Ihnen nicht nur wie üblich, mit den Methoden get() und put() auf die Elemente einer Map zuzugreifen, sondern dafür die Index-Operatoren zu verwenden.

groovy> richtungen = [n:'Nord',s:'Süd',o:'Ost',w:'West']
groovy> richtungen['nw'] = 'Nordwest'
groovy> println richtungen['nw']
Nordwest

Wenn die Schlüssel wie in diesem Fall Strings sind und den Groovy-Namensregeln gehorchen, können Sie auf die Map-Elemente auch zugreifen wie auf die Properties eines Objekts.

groovy> richtungen.oso = 'Ost-Südost'
groovy> println richtungen.oso
Ost-Südost

Sogar wenn die Namensregeln nicht eingehalten werden, können Sie diese Notation anwenden. Sie müssen in diesem Fall nur den Elementschlüssel in Anführungszeichen schreiben.

groovy> richtungen.'o-so' = 'Ost-Südost'
groovy> println richtungen.'o-so'
Ost-Südost

Das geht sogar mit interpolierten GStrings.

groovy> keyOst = 'o'
groovy> keySüdost = 'so'
groovy> println richtungen."$keyOst-$keySüdost"
Ost-Südost

Die Property-Notation für Map-Elemente kann Programme unter Umständen viel übersichtlicher machen. Dies gilt beispielsweise, wenn Sie in Ihrer Map numerische Werte haben, mit denen Sie auch rechnen möchten.

groovy> rechteck = [breite:2.0, höhe:4.5]
groovy> rechteck.breite++
groovy> rechteck.fläche = rechteck.breite * rechteck.höhe
===> 13,5

Wir wollen Sie nicht mit fortwährenden Code-Vergleichen zwischen Java und Groovy langweilen, aber hier lohnt es sich doch einmal, ein äquivalentes Programmstück in Java anzusehen:

//java
// 1. Zeile
Map rechteck = new HashMap();
rechteck.put("breite",new BigDecimal("2.0"));
rechteck.put("höhe",new BigDecimal("4.5"));
// 2. Zeile
rechteck.put("breite",rechteck.get("breite").add(new BigDecimal(1)));
// 3. Zeile
rechteck.put("fläche",rechteck.get("breite").multiply(rechteck.get("höhe")));

Da auch Objekte vom Typ Properties das Interface Map implementieren, gilt diese Notation auch für die System-Properties. Wenn die Namen der Properties Punkte oder andere Zeichen enthalten, die nicht den Groovy-Namensregeln entsprechen, müssen sie in Anführungszeichen gesetzt werden.

groovy> println System.properties.'java.version'
groovy> println System.properties.'os.name'
1.5.0_11
Windows XP

Die Möglichkeit, auf Map-Elemente wie auf die Properties eines Objekts zuzugreifen, macht die Programmierung mancher Klassen überflüssig, die nur als Container für Daten dienen sollen und keine spezifische Funktionalität enthalten.

Solche Klassen entsprechen dem Java-Pattern Daten-Transfer-Objekte (DTO)

Im Kapitel ##DYNAMIK## zeigen wir Ihnen eine kleine Erweiterung zu den Maps, durch die Sie ihnen sogar eigene Funktionalität verleihen können.

Auf eine Besonderheit müssen wir Sie noch hinweisen: Im Gegensatz zu den meisten Objekten können Sie die Klasse einer Map oder einer Hashtable nicht einfach über die Property class abfragen.

groovy> println "ein String".class
class java.lang.String
groovy> println rechteck.class
null

Die Ursache dafür besteht darin, dass aufgrund entsprechender vordefinierter Methoden alle Property-Abfragen bei Maps auf Abfragen nach den Map-Elementen umgelenkt werden. Aus rechteck.class macht Groovy also rechteck.get('class'), und ein Element namens »class« gibt es in dieser Map nicht. Wenn Sie also in einem Programm den Typ eines Objekts erfahren möchten, ist es in der Regel besser, die Methode getClass() anstatt der Property-Abfrage zu verwenden.

groovy println rechteck.getClass()
class java.util.HashMap

Vordefinierte Methoden Bearbeiten

Auch für Maps enthält die Groovy-Laufzeitbibliothek eine Reihe vordefinierter Methoden. Zum Teil dienen sie dazu, die obigen vereinfachten Zugriffsmöglichkeiten zu implementieren, zum Teil stellen sie Ihnen etwas zusätzliche Funktionalität zur Verfügung.

Sicher eine der in Java am häufigsten vermissten Methoden für Maps ist die get()-Methode mit Vorgabewert.

groovy> richtungen = [n:'Nord',s:'Süd',o:'Ost',w:'West']
groovy> schlüssel = 'oso'
groovy> println richtungen.get(schlüssel,'unbekannte Richtung')
unbekannte Richtung

Mit Hilfe der Methode subMap() können Sie eine neue Map bilden, die alle Schlüsselwerte enthält, die sich auch in der übergebenen Collection befinden.

groovy> liste = ['n','s']
groovy> println richtungen.subMap(liste)

Die in Groovy für alle Objekte definierten iterativen Methoden sind für Maps so implementiert, dass sie über Objekte vom Typ java.util.Map.Entry iterieren.

groovy> richtungen = [n:'Nord',s:'Süd',o:'Ost',w:'West']
groovy> richtungen.each { println it }
o=Ost
n=Nord
w=West
s=Süd

Folgendes Beispiel sucht alle Elemente, deren Wert auf »st« endet, und liefert sie als neue Map.

groovy> auswahl = richtungen.findAll { it.value ==~ /.*st/ }
groovy> println auswahl
["w":"West", "o":"Ost"]

Allerdings gibt es noch einige Besonderheiten. So kann etwa die Methode each() auch zwei Parameter haben. Wenn dies der Fall ist, werden ihr bei jedem Durchgang der Schlüssel und der Wert des jeweiligen Map-Elements einzeln übergeben.

groovy> richtungen = [n:'Nord',s:'Süd',o:'Ost',w:'West']
groovy> richtungen.each { key, value -> println "Schlüssel=$key, Wert=$value" }
Schlüssel=o, Wert=Ost
Schlüssel=n, Wert=Nord
Schlüssel=w, Wert=West
Schlüssel=s, Wert=Süd