Du liest:
Die Java forEach Methode (mit Codebeispielen)

Die Java forEach Methode (mit Codebeispielen)

von Pero
22.06.2020
Die Java forEach Methode

Mit Java 8 kamen eine Menge neuer Methoden in die Schnittstellen. Unter anderem neue Datums- und Zeit-APIs, Streams, Lambdas und die Java forEach-Methode. Von all diesen neuen Spielzeugen sind die Lambdas wahrscheinlich das meist diskutierte; und das auch aus gutem Grund. Die Lambdas machen die funktionale Programmierung in Java erst möglich. Funktionales Programmieren ist ein wichtiges Thema, soll aber nicht unser Thema für diesen Artikel sein. Vielmehr werden wir über forEach-Methode sprechen. Auf gewisse Weise werden wir zwar mit Lambdas und der funktionalen Programmierung in Berührung kommen, werden uns aber auf die forEach-Methode konzentrieren.

Um forEach nicht mit der erweiterten for-Schleife zu verwechseln, ist die forEach-Methode zu der Schnittstelle des „Iterable“ hinzugefügt worden. Wir erinnern uns daran, dass die Iterable-Schnittstelle ein Supertyp für Schnittstellen und Klassen im „Java Collection Framework“(JCF) ist.

Einführung – Java forEach

Durch das Hinzufügen der forEach-Methode zu „Iterable“, kann die Methode natürlich auch von allen anderen im „JCF“ verwendet werden. Die forEach-Methode ist als Ersatz bzw. Verbesserung für die klobigen Schleifenmechanismen von Java entwickelt worden. Die aktualisierte for-Schleife ist grundsätzlich nicht schlecht, da sie gegenüber der traditionellen Schleife schon eine deutliche Verbesserung ist. Betrachten wir dafür einmal folgenden Code:

List<String> namen = Arrays.asList("Alvin","Theodore","Simon");

for (String name : namen) {
  System.out.println(name);
}

Wir sehen, dass die Schleife eigentlich garnicht so hässlich ist. Es sieht eigentlich relativ sauber aus. Aber schauen wir uns dagegen einmal die Version mit der forEach-Methode an:

names.forEach( name -> System.out.println(name));

Wie wir sehen, ist der Audruck deutlich aussagekräftiger. Wenn wir uns noch nicht viel mit funktionaler Programmierung beschäftigt haben, sieht der Ausdruck zunächst komisch aus. Aber dafür können wir uns den Ausdruck ja etwas aufschlüsseln.

Grundsätzlich ist wichtig, dass es sich bei der forEach um keine Anweisung wie bei der for-Schleife oder der erweiterten for-Schleifen handelt, sondern eine Methode, die auf alle Sammelobjekte und Streams angewendet werden kann.

Der Pfeil-Operator, den wir als „->“ schreiben, wird auch als Lambda-Operator bezeichnet. Dieser ist erforderlich, um den Parameter vom Lambda-Körper zu trennen. Der Lambda-Körper kann entweder ein Ausdruck oder ein gesamter Anweisungsblock sein.

In unserem forEach-Beispiel steht die Namensvariable (auf der linken Seite des „->“) für jedes Element in der Namen-Liste. Die Print-Funktion auf der rechten Seite des „->“ ist der Lambda-Körper. Er steht in diesem Fall ohne Klammern, da es sich nur um eine Anweisung handelt. Man könnte aber genauso gut auch Klammern nutzen.

names.forEach( name -> {
  System.out.println(name);
});

Die Elemente der Sammlung (Namen-Liste) sind für den Lambda-Körper zugänglich, deshalb können wir diese in der println()-Funktion nutzen.

Wir können auch Methodenverweise nutzen, um eine kompakte und einfache Form der Lambda-Ausdrücke zu erhalten. Wenn wir das vorherige Beispiel mit einem Methodenverweis formulieren wollen, sieht es wie folgt aus:

names.forEach(System.out::println);

Ein Methodenverweis kann sich auf drei Typen beziehen:

  1. auf die statische Methode, dir wir gerade verwenden wollen
  2. eine Instanz-Methode
  3. einen Konstruktor

Nutzung der Java forEach Methode

Alle Iterablen Typen (d.h. praktisch alle Typen die Sammlungen darstellen) haben die gleiche Syntax für die Verwendung der forEach-Methode.

Um also über eine Liste von Strings zu iterieren, können wir den folgenden Code verwenden:

List<String> names = Arrays.asList("Alvin","Theodore","Simon");
names.forEach(System.out::println);

Wenn wir ein Set verwenden wollen, funktioniert das ähnlich:

Set<String> namen = new HashSet<>(Arrays.asList("Alvin", "Theodore", "Simon"));
namen.forEach(System.out::println);

Wir können forEach auch mit Maps verwenden, selbst wenn diese eine eigentlich nicht iterierbare Schnittstellen besitzen. Die Map-Schnittstelle bietet deshalb eine ähnliche Implementierung für forEach. Die Lambda-Aktionen können gleichzeitig mit dem Schlüssel und dem Wert der Map ausgeführt werden.

fruechte.put(1, "Apple");
fruechte.put(2, "Orange");
fruechte.put(3, "Banana");

fruechte.forEach((key, value) -> {
  System.out.printf("Schlüssel:%s | Wert:%s\n", key,value);
});

Interne und externe Iteratoren

Die for-Schleife und die forEach-Methode lassen sich darin unterscheiden, welche Art von Iteratoren sie verwenden. Die forEach-Methode verwendet einen internen Iterator, während die for-Schleife einen externen Iterator verwendet.

Ein Ausdruck, bei dem interne Iteratoren verwendet werden, sieht wie folgt aus:

namen.forEach( name -> {
  System.out.println(name);
});

Jedes Element der Sammlung wird automatisch dem Lambda-Ausdruck (Name) zur Verfügung gestellt. Innerhalb des Lambda-Körpers geht es uns dann nur darum, mit den Daten (den Elementen in der Sammlung) das zu machen, was notwendig ist. Wir müssen nicht angeben, wie wir die Iterationen durchführen wolle. Wir müssen keine Schritte, keine next()- oder hasNext()-Methoden verwenden. Somit haben wir einfach eine Operation an den Daten durchgeführt. Die Iteration wurde automatisch durchgeführt.

Eine for-Schleife würde wie folgt aussehen:

for (String name : names) {
  System.out.println(name);
}

Selbst wenn wir die hasNext()-, Iterator()- und next()-Methoden in diesem Beispiel nicht sehen, ist es das, was die for-Schleife untersichtbar vor uns macht (sie ist praktisch eine Vereinfachung der Schreibweise). In der Klammer der for-Schleife können wir die Iterationen selbst steuern. Wir können die Schritte dirigieren, da wir einen externen Iterator haben. Im Gegensatz zu einem internen Iterator, bei dem wir uns auf die Methode zur Iteration verlassen müssen, haben wir hier die volle Kontrolle.

Zusammenfassung

Die Java forEach-Methode ist eine neue Methode, die allen JCF-Klassen seit Java 8, die Möglichkeit einräumt, übersichtlich und einfach die entsprechende Sammlung zu durchqueren (iterieren). Bei der forEach-Methode wird ein interner Iterator verwendet, der uns im Gegensatz zur herkömmlichen for-Schleife keine Kontrolle über die Iteration gibt. Normalerweise erwartet die forEach-Methode ein Objekt vom Typ der Consumer-Schnittstelle (das ist aber wiederum ein ganz anderes Thema). Vorerst verwenden wir deshalb nur die Lambda-Ausdrücke in Verbindung mit der forEach-Methode.



Bislang gibt es keine Kommentare. Markier dein Revier und sei der Erste!

Schreibe einen Kommentar

Das könnte dich auch interessieren