Die Anleitung zu Java Stream
1. Stream
Java 8 führt ein neues Konzept namens Stream ein. Wenn Sie zum ersten Mal über Stream API lesen, können Sie verwirren, denn der Name InputStream und OutputStream ähnelt, Java 8 Stream jedoch etwas ganz ändert. Stream ist eine Monade, daher spielt es eine wichtige Rolle, um funktionale Programmierung in Java zu bringen.
Vor dem Beginn des Artikel schlage ich Sie vor, den Konzept functional interface und einige üblichen functional interface wie Supplier, Consumer, Predicate zu lernen. Unten sind das meine Artikels:
Im funktionelle Programmierung ist eine Monade eine Struktur, die eine Berechnung (computation) darstellt, die eine Reihe von miteinander verbundenen Schritten erfordert. Zum Einfachen sehen Sie das Beispiel über die folgende Monade:
List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList
.stream() // (1) return a Stream
.filter(s -> s.startsWith("c")) // (2) return a new Stream
.map(String::toUpperCase) // (3) return a new Stream
.sorted() // (4) return a new Stream
.forEach(System.out::println); // (5)
Output:
C1
C2
- Ein Stream aus einem Objekt List erstellen.
- Ein neues Stream aus einem vorhandenen Stream erstellen und fasst die Elemente um, die mit "c" beginnt.
- Ein neues Stream aus einem vorhandenen Stream erstellen und alle Elementen wird zum Großbuchstabe umgewandelt.
- Ein neues Stream aus einem vorhandenen Stream erstellen, indem die Elemente reorganisiert werden.
- Die Elemente von letzten Stream ausdrucken.
In diesem obengemeinten Beispiel sind die Schritten von (2) zum (4) die mitleren Aktionen (intermediate operation) denn sie geben ein Objekt Stream zurück. Deshalb können Sie eine andere Methodes von Stream aufrufen ohne es mit einem Komma zu enden.
Die Terminal Operaton ist eine Methode, die void oder ein anderes Typ als Stream zurückgibt. In diesem Beispiel ist der Schritt 5 eine Terminal Operation denn die Methode Stream.forEach gibt void zurück.
Danach sind das die Eigenschaften und Vorteile von Java 8 Stream:
- Nicht lagern. Stream ist keine Datenstruktur, sondern nur eine Ansicht der Datenquelle (Es kann ein Array, eine Liste oder ein I/O Channel,usw sein.).
- Ein Stream ist eine natürliche Funktion. Mit der Änderungen für Stream wird die Datenquelle nicht geändert. Z.B: Durch das Filtern eines Stream werden keine Elemente gelöscht, sondern ein neuer Stream erstellt, der die gefilterten Elemente enthält.
- Faule Ausführung. Die Aktivitäten auf Stream werden nicht sofort ausgeführt. Sie werden nur ausgeführt, wenn der Benutzer die Ergebnisse wirklich benötigt.
- Verbrauchbar (Consumable). Auf die Elemente von Stream wird während der Lebensdauer von Stream nur einmal zugegriffen. Nach der Genehmigung wird Stream wie einem Iterator deaktiviert. Sie müssen einen neuen Stream neu erstellen wenn Sie Stream wieder ansehen möchten.
Sehen Sie die folgende Abbildung um besser zu verstehen, wie Stream funktioniert.
- Erstellen Sie einen stream aus einer Sammlung (collection).
- Filtern Sie die andere Farbe als rot.
- Malen Sie die Dreiecke rosa.
- Filtern Sie die andere Formen als Quadrate.
- Berechnen Sie die Gesamtfläche.
Die Klasse Employee nehmen an die einigen Beispiele in diesem Artikel teil:
Employee.java
package org.o7planning.stream.ex;
public class Employee {
private String name;
private float salary;
private String gender; // "M", "F"
public Employee(String name, float salary, String gender) {
this.name = name;
this.salary = salary;
this.gender = gender;
}
public String getName() {
return name;
}
public float getSalary() {
return salary;
}
public String getGender() {
return gender;
}
public boolean isFemale() {
return "F".equals(this.getGender());
}
}
2. Stream.filter(Predicate)
Geben Sie einen Stream zurück, einschließend die Elementen von Stream entsprechen der angegebenen Predicate .
Stream<T> filter(Predicate<? super T> predicate)
Z.B: Aus einer Liste der Mitarbeiter (Employee) drucken Sie die Liste der weiblichen Mitarbeiterinnen, deren Gehalt größer als 2500 ist.
Stream_filter_ex1.java
package org.o7planning.stream.ex;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Stream_filter_ex1 {
public static void main(String[] args) {
Employee john = new Employee("John P.", 1500, "M");
Employee sarah = new Employee("Sarah M.", 2000, "F");
Employee charles = new Employee("Charles B.", 1700, "M");
Employee mary = new Employee("Mary T.", 5000, "F");
Employee sophia = new Employee("Sophia B.", 7000, "F");
List<Employee> employees = Arrays.asList(john, sarah, charles, mary, sophia);
// Employee is Female and salary > 2500
Predicate<Employee> predicate = e -> e.isFemale() && e.getSalary() > 2500;
employees //
.stream() //
.filter(predicate) //
.forEach(e -> System.out.println(e.getName()+ " : " + e.getSalary()));
}
}
Output:
Mary T. : 5000.0
Sophia B. : 7000.0
Wenn eine nicht-statische Methode ohne Parameter einen Wert boolean zurückgibt, gilt ihre Referenz als eine Predicate. (Sehen Sie meinen Artikel über Java Predicate mehr).
Z.B: Erstellen Sie eine Predicate aus der Methode-Referenz:
Predicate<Employee> p = Employee::isFemale;
// Same as:
Predicate<Employee> p = employee -> employee.isFemale();
Stream_filter_ex2.java
package org.o7planning.stream.ex;
import java.util.Arrays;
import java.util.List;
public class Stream_filter_ex2 {
public static void main(String[] args) {
Employee john = new Employee("John P.", 1500, "M");
Employee sarah = new Employee("Sarah M.", 2000, "F");
Employee charles = new Employee("Charles B.", 1700, "M");
Employee mary = new Employee("Mary T.", 5000, "F");
Employee sophia = new Employee("Sophia B.", 7000, "F");
List<Employee> employees = Arrays.asList(john, sarah, charles, mary, sophia);
employees //
.stream() //
.filter(Employee::isFemale) //
.forEach(e -> System.out.println(e.getName()+ " : " + e.getSalary()));
}
}
Output:
Sarah M. : 2000.0
Mary T. : 5000.0
Sophia B. : 7000.0
3. Stream.sorted(Comparator)
Geben Sie einen Stream zurück, einschließend die Elemente dieses Stream, die nach dem angegebenen Comparator zugeordnet werden.
Stream<T> sorted(Comparator<? super T> comparator)
- Die Anleitung zu Java Comparator
Z.B: Ordnen Sie die Mitarbeiter nach der steigenden Reihenfolge zu:
Stream_sort_ex1.java
package org.o7planning.stream.ex;
import java.util.Arrays;
import java.util.List;
public class Stream_sort_ex1 {
public static void main(String[] args) {
Employee john = new Employee("John P.", 1500, "M");
Employee sarah = new Employee("Sarah M.", 2000, "F");
Employee charles = new Employee("Charles B.", 1700, "M");
Employee mary = new Employee("Mary T.", 5000, "F");
Employee sophia = new Employee("Sophia B.", 7000, "F");
List<Employee> employees = Arrays.asList(john, sarah, charles, mary, sophia);
employees //
.stream() //
.sorted (
(e1,e2) -> (int) (e1.getSalary() - e2.getSalary())
) //
.forEach(e -> System.out.println(e.getSalary() + " : " + e.getName()));
}
}
Output:
1500.0 : John P.
1700.0 : Charles B.
2000.0 : Sarah M.
5000.0 : Mary T.
7000.0 : Sophia B.
Z.B: Ordnen Sie die Mitarbeiter nach dem Geschecht (Gender) und Gehalt:
Stream_sort_ex2.java
package org.o7planning.stream.ex;
import java.util.Arrays;
import java.util.List;
public class Stream_sort_ex2 {
public static void main(String[] args) {
Employee john = new Employee("John P.", 1500, "M");
Employee sarah = new Employee("Sarah M.", 2000, "F");
Employee charles = new Employee("Charles B.", 1700, "M");
Employee mary = new Employee("Mary T.", 5000, "F");
Employee sophia = new Employee("Sophia B.", 7000, "F");
List<Employee> employees = Arrays.asList(john, sarah, charles, mary, sophia);
employees //
.stream() //
.sorted (
(e1,e2) -> {
int v = e1.getGender().compareTo(e2.getGender());
if(v == 0) {
v = (int) (e1.getSalary() - e2.getSalary());
}
return v;
}
) //
.forEach(e -> System.out.println(e.getGender()+ " : "+ e.getSalary() + " : " + e.getName()));
}
}
Output:
F : 2000.0 : Sarah M.
F : 5000.0 : Mary T.
F : 7000.0 : Sophia B.
M : 1500.0 : John P.
M : 1700.0 : Charles B.
4. Stream.map(Function)
Geben Sie einen neuen Stream zurück, einschließend die Ergebnisse der angegebenen Function für die Elemente von Stream.
<R> Stream<R> map(Function<? super T,? extends R> mapper)
Z.B: Wandeln Sie eine Liste von String zur Großbuchstabe um (uppercase).
Stream_map_ex1.java
package org.o7planning.stream.ex;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Stream_map_ex1 {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
List<String> newList = list //
.stream() // a Stream
.map(s -> s.toUpperCase()) // a new Stream
.collect(Collectors.toList()); // Stream => List
System.out.println(list); // [a, b, c, d, e]
System.out.println(newList); // [A, B, C, D, E]
}
}
Wenn eine nicht-statische Methode (non-static method) ohne Parameter und einen Wert zurückgibt, wird ihr Referenz als eine Function betrachten. (Sehen Sie mehr die Erklärung in meinem Artikel über Java Function).
// Create a Function from a method reference:
Function<String, String> f1 = String::toUpperCase;
// Same as:
Function<String, String> f2 = s -> s.toUpperCase();
Stream_map_ex2.java
package org.o7planning.stream.ex;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Stream_map_ex2 {
public static void main(String[] args) {
List<String> list = Arrays.asList("a", "b", "c", "d", "e");
List<String> newList = list //
.stream() // a Stream
.map(String::toUpperCase) // a new Stream
.collect(Collectors.toList()); // Stream => List
System.out.println(list); // [a, b, c, d, e]
System.out.println(newList); // [A, B, C, D, E]
}
}
Z.B: Doppelte Gehaltserhöhung für jeden Mitarbeiter in einer Liste:
Stream_map_ex3.java
package org.o7planning.stream.ex;
import java.util.Arrays;
import java.util.List;
public class Stream_map_ex3 {
public static void main(String[] args) {
Employee john = new Employee("John P.", 1500, "M");
Employee sarah = new Employee("Sarah M.", 2000, "F");
Employee charles = new Employee("Charles B.", 1700, "M");
Employee mary = new Employee("Mary T.", 5000, "F");
Employee sophia = new Employee("Sophia B.", 7000, "F");
List<Employee> employees = Arrays.asList(john, sarah, charles, mary, sophia);
employees //
.stream() // a Stream.
.map((e) -> new Employee(e.getName(), e.getSalary()* 2, e.getGender())) // a new Stream.
.forEach(c -> System.out.println(c.getName()+ " : " + c.getSalary()));
}
}
Output:
John P. : 3000.0
Sarah M. : 4000.0
Charles B. : 3400.0
Mary T. : 10000.0
Sophia B. : 14000.0
Java Grundlagen
- Anpassen von Java-Compiler, der Ihre Annotation verarbeitet (Annotation Processing Tool)
- Java Programmierung für Team mit Eclipse und SVN
- Die Anleitung zu Java WeakReference
- Die Anleitung zu Java PhantomReference
- Komprimierung und Dekomprimierung in Java
- Konfigurieren von Eclipse zur Verwendung des JDK anstelle von JRE
- Java-Methoden String.format() und printf()
- Syntax und neue Funktionen in Java 8
- Die Anleitung zu Java Reguläre Ausdrücke
- Die Anleitung zu Java Multithreading Programming
- JDBC Driver Bibliotheken für verschiedene Arten von Datenbank in Java
- Die Anleitung zu Java JDBC
- Holen Sie sich die automatisch erhöhenden Wert der Spalte bei dem Insert eines Rekord, der JDBC benutzt
- Die Anleitung zu Java Stream
- Die Anleitung zu Java Functional Interface
- Einführung in Raspberry Pi
- Die Anleitung zu Java Predicate
- Abstrakte Klasse und Interface in Java
- Zugriffsmodifikatoren (Access modifiers) in Java
- Die Anleitung zu Java Enum
- Die Anleitung zu Java Annotation
- Vergleichen und Sortieren in Java
- Die Anleitung zu Java String, StringBuffer und StringBuilder
- Die Anleitung zu Java Exception
- Die Anleitung zu Java Generics
- Manipulieren von Dateien und Verzeichnissen in Java
- Die Anleitung zu Java BiPredicate
- Die Anleitung zu Java Consumer
- Die Anleitung zu Java BiConsumer
- Was ist erforderlich, um mit Java zu beginnen?
- Geschichte von Java und der Unterschied zwischen Oracle JDK und OpenJDK
- Installieren Sie Java unter Windows
- Installieren Sie Java unter Ubuntu
- Installieren Sie OpenJDK unter Ubuntu
- Installieren Sie Eclipse
- Installieren Sie Eclipse unter Ubuntu
- Schnelle lernen Java für Anfänger
- Geschichte von Bits und Bytes in der Informatik
- Datentypen in Java
- Bitweise Operationen
- if else Anweisung in Java
- Switch Anweisung in Java
- Schleifen in Java
- Die Anleitung zu Java Array
- JDK Javadoc im CHM-Format
- Vererbung und Polymorphismus in Java
- Die Anleitung zu Java Function
- Die Anleitung zu Java BiFunction
- Beispiel für Java Encoding und Decoding mit Apache Base64
- Die Anleitung zu Java Reflection
- Java-Remote-Methodenaufruf - Java RMI
- Die Anleitung zu Java Socket
- Welche Plattform sollten Sie wählen für Applikationen Java Desktop entwickeln?
- Die Anleitung zu Java Commons IO
- Die Anleitung zu Java Commons Email
- Die Anleitung zu Java Commons Logging
- Java System.identityHashCode, Object.hashCode und Object.equals verstehen
- Die Anleitung zu Java SoftReference
- Die Anleitung zu Java Supplier
- Java Aspect Oriented Programming mit AspectJ (AOP)
Show More
- Anleitungen Java Servlet/JSP
- Die Anleitungen Java Collections Framework
- Java API für HTML & XML
- Die Anleitungen Java IO
- Die Anleitungen Java Date Time
- Anleitungen Spring Boot
- Anleitungen Maven
- Anleitungen Gradle
- Anleitungen Java Web Services
- Anleitungen Java SWT
- Die Anleitungen JavaFX
- Die Anleitungen Oracle Java ADF
- Die Anleitungen Struts2 Framework
- Anleitungen Spring Cloud