Java-Ströme: Ein Anfängerleitfaden

Hallo da drüben, zukünftige Java-Zauberer! Heute begeben wir uns auf eine aufregende Reise in die Welt der Java-Ströme. Machen Sie sich keine Sorgen, wenn Sie neu im Programmieren sind – ich werde Ihr freundlicher Guide sein, und wir gehen das Schritt für Schritt durch. Am Ende dieses Tutorials werden Sie Daten wie ein Profi streamen können!

Java - Streams

Was ist ein Strom in Java?

Stellen Sie sich vor, Sie sind in einem Sushi-Buffet-Restaurant, wo die Sushi-Platten kontinuierlich an Ihnen vorbeilaufen und Sie auswählen können, was Sie möchten. Genau das ist ein Strom in Java – eine Sequenz von Elementen, die Sie einzeln verarbeiten können, ohne sie alle gleichzeitig im Speicher speichern zu müssen.

Ströme wurden in Java 8 eingeführt, um das Arbeiten mit Datenkollektionen einfacher und effizienter zu machen. Sie ermöglichen es uns, Daten auf eine mehr宣言式 Weise zu bearbeiten, indem wir Java sagen, was wir tun möchten, anstatt wie wir es tun möchten.

Erstellen von Strömen in Java

Lassen Sie uns mit der Erstellung unseres ersten Stroms beginnen. Es gibt mehrere Möglichkeiten, dies zu tun, aber wir fangen mit einem einfachen Beispiel an:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class StreamExample {
public static void main(String[] args) {
// Erstellen eines Stroms aus einer Liste
List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
Stream<String> fruitStream = fruits.stream();

// Direktes Erstellen eines Stroms
Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5);
}
}

In diesem Beispiel haben wir zwei Ströme erstellt. Der erste, fruitStream, wird aus einer Liste von Früchten erstellt. Der zweite, numberStream, wird direkt mit der Stream.of()-Methode erstellt.

Gemeinsame Stromoperationen

Nun, da wir unsere Ströme haben, schauen wir uns einige gemeinsame Operationen an, die wir auf sie anwenden können.

forEach-Methode

Die forEach-Methode ist wie ein freundlicher Roboter, der durch jedes Element in Ihrem Strom geht und etwas damit macht. Lassen Sie uns verwenden, um unsere Früchte zu drucken:

fruits.stream().forEach(fruit -> System.out.println(fruit));

Dies wird ausgeben:

apple
banana
cherry
date

Hier ist fruit -> System.out.println(fruit) eine Lambda-Ausdrücke. Es ist eine Kurzform, um Java zu sagen, was mit jedem Element getan werden soll.

map-Methode

Die map-Methode ist wie eine magischestab, der jedes Element im Strom transformiert. Lassen Sie uns verwenden, um alle unsere Früchte in Großbuchstaben zu konvertieren:

List<String> upperCaseFruits = fruits.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upperCaseFruits);

Dies wird ausgeben:

[APPLE, BANANA, CHERRY, DATE]

Das String::toUpperCase ist ein Methodenverweis, ein weiteres cooles Java-FEATURE, das so viel bedeutet wie "verwenden Sie die toUpperCase-Methode auf jedem String".

filter-Methode

Die filter-Methode ist wie ein Türsteher in einem Club, der nur bestimmte Elemente durchlässt. Lassen Sie uns verwenden, um nur die Früchte zu behalten, die mit 'a' beginnen:

List<String> aFruits = fruits.stream()
.filter(fruit -> fruit.startsWith("a"))
.collect(Collectors.toList());
System.out.println(aFruits);

Dies wird ausgeben:

[apple]

limit-Methode

Die limit-Methode ist wie "Ich möchte nur so viele, danke!" Sie beschränkt den Strom auf eine bestimmte Anzahl von Elementen:

List<String> firstTwoFruits = fruits.stream()
.limit(2)
.collect(Collectors.toList());
System.out.println(firstTwoFruits);

Dies wird ausgeben:

[apple, banana]

sorted-Methode

Die sorted-Methode ist wie das Arrangieren Ihres Bücherregals. Sie ordnet die Elemente in einer Reihenfolge:

List<String> sortedFruits = fruits.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedFruits);

Dies wird ausgeben:

[apple, banana, cherry, date]

Parallelverarbeitung

Eine der coolen Eigenschaften von Strömen ist, dass sie leicht parallel verarbeitet werden können, was die Verarbeitung großer Datensätze möglicherweise beschleunigt. Sie können einen parallelen Strom如此 erstellen:

fruits.parallelStream().forEach(fruit -> System.out.println(fruit + " " + Thread.currentThread().getName()));

Dies könnte ausgeben:

banana ForkJoinPool.commonPool-worker-1
apple main
date ForkJoinPool.commonPool-worker-2
cherry ForkJoinPool.commonPool-worker-3

Die Reihenfolge könnte bei jedemlauf unterschiedlich sein, da die Früchte parallel verarbeitet werden!

Collectors

Collectors sind spezielle Werkzeuge, die uns helfen, die Ergebnisse von Stromoperationen zu sammeln. Wir haben collect(Collectors.toList()) in unseren Beispielen verwendet, um unsere Stromergebnisse wieder in Listen umzuwandeln. Es gibt viele andere nützliche Collectors:

// Elemente in eine Zeichenkette einfügen
String fruitString = fruits.stream().collect(Collectors.joining(", "));
System.out.println(fruitString);  // Gibt aus: apple, banana, cherry, date

// Elemente zählen
long fruitCount = fruits.stream().collect(Collectors.counting());
System.out.println(fruitCount);  // Gibt aus: 4

// Elemente gruppieren
Map<Character, List<String>> fruitGroups = fruits.stream()
.collect(Collectors.groupingBy(fruit -> fruit.charAt(0)));
System.out.println(fruitGroups);  // Gibt aus: {a=[apple], b=[banana], c=[cherry], d=[date]}

Statistiken

Ströme können uns auch dabei helfen, Statistiken zu numerischen Daten zu berechnen:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt(Integer::intValue).summaryStatistics();
System.out.println("Anzahl: " + stats.getCount());
System.out.println("Summe: " + stats.getSum());
System.out.println("Minimum: " + stats.getMin());
System.out.println("Maximum: " + stats.getMax());
System.out.println("Mittelwert: " + stats.getAverage());

Dies wird ausgeben:

Anzahl: 5
Summe: 15
Minimum: 1
Maximum: 5
Mittelwert: 3.0

Java-Ströme Beispiel

Lassen Sie uns alles zusammenbringen mit einem komplexeren Beispiel. Stellen Sie sich vor, wir haben eine Liste von Schülern mit ihrem Alter und ihren Noten:

class Student {
String name;
int age;
double grade;

Student(String name, int age, double grade) {
this.name = name;
this.age = age;
this.grade = grade;
}
}

public class StreamExample {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Alice", 22, 90.5),
new Student("Bob", 20, 85.0),
new Student("Charlie", 21, 92.3),
new Student("David", 23, 88.7)
);

// Durchschnittsnote der Schüler über 21
double averageGrade = students.stream()
.filter(student -> student.age > 21)
.mapToDouble(student -> student.grade)
.average()
.orElse(0.0);

System.out.println("Durchschnittsnote der Schüler über 21: " + averageGrade);

// Namen der besten 2 Schüler nach Note
List<String> topStudents = students.stream()
.sorted((s1, s2) -> Double.compare(s2.grade, s1.grade))
.limit(2)
.map(student -> student.name)
.collect(Collectors.toList());

System.out.println("Beste 2 Schüler: " + topStudents);
}
}

Dieses Beispiel zeigt, wie wir mehrere Stromoperationen aneinander ketten können, um komplexe Datenverarbeitungsaufgaben auf eine prägnante und lesbare Weise durchzuführen.

Und da haben Sie es, Leute! Sie haben gerade Ihre ersten Schritte in die Welt der Java-Ströme gemacht. Denken Sie daran, dass Übung den Meister macht,also experimentieren Sie nicht mit diesen Konzepten. Vor Ihnen wissen Sie, dass Sie Daten wie ein Profi streamen werden! Frohes Programmieren!

Credits: Image by storyset