1. Transformation von Collection-Elementen
In der Programmierung gehört die Transformation einer Collection zu den häufigsten Operationen: Wir haben eine Collection von Daten eines Typs und müssen darauf basierend eine neue Collection eines anderen Typs erstellen. Zum Beispiel aus einer Liste von Objekten des Typs User eine Liste ihrer Namen (String) oder aus einer Liste von Zahlen eine Liste ihrer Quadrate.
Der grundlegendste und verständlichste Ansatz in Java ist der imperative Ansatz, also eine normale for-Schleife (oft als for-each).
Beispiel: Aus einer Liste von Strings eine Liste ihrer Längen erzeugen
Nehmen wir an, wir haben eine Liste von Stadtnamen:
List<String> cities = List.of("London", "Paris", "Tokio", "New York");
Unsere Aufgabe ist es, eine neue Liste zu erstellen, die die Länge jedes Namens enthält. Das Endergebnis sollte sein: [6, 5, 5, 8].
Lösung mit einer for-Schleife:
import java.util.ArrayList;
import java.util.List;
public class CollectionTransform {
public static void main(String[] args) {
List<String> cities = List.of("London", "Paris", "Tokio", "New York");
List<Integer> lengths = new ArrayList<>(); // Wir erstellen eine neue, leere Liste für das Ergebnis
for (String city : cities) {
// Für jedes Element aus cities berechnen wir seine Länge ...
int length = city.length();
// ... und fügen dieses Ergebnis der neuen Liste hinzu
lengths.add(length);
}
System.out.println(lengths); // Wird ausgeben: [6, 5, 5, 8]
}
}
Wir beginnen mit einer neuen, leeren Collection für die Ergebnisse – die Transformation verändert die Ausgangs-Collection nicht. Zum Durchlaufen der ursprünglichen Collection verwenden wir eine for-each-Schleife und wenden innerhalb die benötigte Logik (length()) auf jedes Element an; das Resultat fügen wir mit add der neuen Liste hinzu.
2. Transformation von Objekten
Häufig arbeiten wir mit komplexeren Datentypen. Angenommen, wir haben eine Klasse Product und möchten eine Liste ihrer Namen (oder Preise) erhalten.
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
}
Nun erhalten wir, ausgehend von einer Produktliste, eine Liste ihrer Namen:
import java.util.ArrayList;
import java.util.List;
public class ProductExample {
public static void main(String[] args) {
List<Product> products = List.of(
new Product("Laptop", 1200.0),
new Product("Maus", 25.5),
new Product("Tastatur", 75.0)
);
// Wir erstellen eine neue Liste für die Namen
List<String> productNames = new ArrayList<>();
for (Product product : products) {
// Für jedes Product-Objekt holen wir seinen Namen
productNames.add(product.getName());
}
System.out.println(productNames); // Wird ausgeben: [Laptop, Maus, Tastatur]
}
}
Die Logik bleibt gleich: Wir iterieren über die Ausgangs-Collection, wenden auf jedes Element die benötigte Methode an (z. B. getName()) und fügen das Ergebnis der neuen Collection hinzu.
3. Arbeiten mit verschachtelten Collections
Betrachten wir den Fall einer Liste von Listen: mehrere Abteilungen, in jeder eine eigene Mitarbeitendenliste. Aufgabe: eine einzige („flache“) Liste aller Mitarbeitenden erstellen.
Beispiel: Zusammenführen von Mitarbeiterlisten
List<List<String>> departments = List.of(
List.of("Anna", "Boris"),
List.of("Viktoria", "Glenn", "Daniel"),
List.of("Elena")
);
Wir möchten eine einzige Liste erhalten: [Anna, Boris, Viktoria, Glenn, Daniel, Elena].
Methode 1: mit der Methode addAll()
import java.util.ArrayList;
import java.util.List;
public class NestedCollectionExample {
public static void main(String[] args) {
List<List<String>> departments = List.of(
List.of("Anna", "Boris"),
List.of("Viktoria", "Glenn", "Daniel"),
List.of("Elena")
);
List<String> allEmployees = new ArrayList<>();
// Wir iterieren über jede Liste (Abteilung)
for (List<String> department : departments) {
// Wir fügen alle Elemente der aktuellen Liste der Gesamtliste hinzu
allEmployees.addAll(department);
}
System.out.println(allEmployees); // [Anna, Boris, Viktoria, Glenn, Daniel, Elena]
}
}
Methode 2: verschachtelte Schleife – dasselbe, aber „von Hand“:
List<List<String>> departments = List.of(...);
List<String> allEmployees = new ArrayList<>();
for (List<String> department : departments) { // Äußere Schleife über Abteilungen
for (String employee : department) { // Innere Schleife über Mitarbeitende
allEmployees.add(employee);
}
}
System.out.println(allEmployees);
Beide Methoden liefern dasselbe Ergebnis. Die Methode addAll() kapselt im Grunde die Logik der verschachtelten Schleife und macht den Code kürzer.
4. Komplexere Fälle und bedingte Transformationen
Manchmal soll die Transformation nur für Elemente ausgeführt werden, die eine Bedingung erfüllen. Beispielsweise möchten wir eine Liste von Stadtnamen erhalten, die mit dem Buchstaben "N" beginnen, und ihre Längen nehmen. Hier kombinieren wir Filterung und Transformation: if + Methodenaufruf (length()).
import java.util.ArrayList;
import java.util.List;
public class ConditionalTransform {
public static void main(String[] args) {
List<String> cities = List.of("London", "Paris", "Tokio", "New York", "Nürnberg");
List<Integer> lengths = new ArrayList<>();
for (String city : cities) {
// Zuerst prüfen wir die Bedingung
if (city.startsWith("N")) {
// Wenn die Bedingung erfüllt ist, wenden wir die Transformation an
lengths.add(city.length());
}
}
System.out.println(lengths); // Wird ausgeben: [8, 8]
}
}
Das Muster ist: Innerhalb der Schleife filtern wir zuerst das Element über eine Bedingung (startsWith, Vergleich, Bereichsprüfung usw.), dann wenden wir die gewünschte Transformation an und legen das Ergebnis in einer neuen Liste ab.
5. Typische Fehler und Fallstricke
Fehler Nr. 1: Änderung der Ausgangs-Collection während der Iteration. Ein häufiger Fehler ist der Versuch, Elemente in der Ausgangs-Collection direkt in der for-each-Schleife hinzuzufügen/zu löschen. Das führt zu Fehlern und unvorhersehbarem Verhalten. Lösung: Erstellen Sie immer eine neue Ergebnisliste und füllen Sie diese.
Fehler Nr. 2: falsches Casting. Wenn Sie mit „rohen“ Collections arbeiten (z. B. über Object) und Elemente auf einen falschen Typ casten, erhalten Sie eine ClassCastException. Verwenden Sie Generics (List<T>) und achten Sie auf Signaturen.
Fehler Nr. 3: ineffiziente Ressourcennutzung. Bei sehr großen Collections kann das ständige Erstellen neuer Listen und Kopieren von Elementen spürbar in Bezug auf Speicher und Zeit sein. In den meisten Alltagsaufgaben ist das akzeptabel, aber bei der Verarbeitung großer Datenmengen sollten Sie die Komplexität berücksichtigen und den Ansatz bei Bedarf optimieren.
GO TO FULL VERSION