Java 8 Streams, eine praktische Einführung | Jeronemo | Skillshare

Playback-Geschwindigkeit


1.0x


  • 0.5x
  • 0.75x
  • 1x (normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Java 8 Streams, eine praktische Einführung

teacher avatar Jeronemo

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Einheiten dieses Kurses

    • 1.

      Einführung

      0:41

    • 2.

      Stream und Verwendung des Kastens

      3:28

    • 3.

      Funktionale Schnittstellen und Lambda

      10:48

    • 4.

      Stream

      1:52

    • 5.

      Zwischenbetrieb: Filter

      1:19

    • 6.

      Terminalbetrieb: forEach

      1:31

    • 7.

      Zwischenbetrieb: Karte

      1:34

    • 8.

      Zwischenbetrieb: flatMap

      2:36

    • 9.

      Intermediate sequentiell und parallel

      2:48

    • 10.

      Zwischenbetrieb: Blick

      1:33

    • 11.

      Terminalbetrieb: Abholung

      4:06

    • 12.

      Terminalbetrieb: Verringerung

      5:11

    • 13.

      Zusammenfassung und Afterword

      1:31

  • --
  • Anfänger-Niveau
  • Fortgeschrittenes Niveau
  • Fortgeschrittenes Niveau
  • Jedes Niveau

Von der Community generiert

Das Niveau wird anhand der mehrheitlichen Meinung der Teilnehmer:innen bestimmt, die diesen Kurs bewertet haben. Bis das Feedback von mindestens 5 Teilnehmer:innen eingegangen ist, wird die Empfehlung der Kursleiter:innen angezeigt.

34

Teilnehmer:innen

--

Projekt

Über diesen Kurs

Die Streams wurden in Java 8 eingeführt, sind aber genauso relevant in Java 11, Java 17 und allen künftigen Versionen. Sie sind ein wesentlicher Aspekt bei der Entwicklung eines besseren Java

Dieser Kurs wird dir alles beibringen, was du über die Java wissen musst, um sie in deinen eigenen Projekten zu verwenden. Sein Ziel ist es, dir Einblick in die Möglichkeiten der Streams zu geben und dir Situationen zu ermöglichen, in denen Streams sinnvoll sein können. Es konzentriert sich hauptsächlich auf diejenigen, die wenig bis gar keine Erfahrung mit Streams und Lambdas haben, kann aber auch als Auffrischungskurs für die am häufigsten verwendeten Operationen und deren Verwendung verwendet werden.

Was du in diesem Kurs lernst:

  • Wie anonyme Interclasses, funktionale Schnittstellen und Lambdas funktionieren und entstehen lassen.
  • Wie Streams im Allgemeinen arbeiten und warum du sie verwenden musst.
  • Wie die am häufigsten verwendeten Operationen in einem Stream funktionieren.

Streams sind ein Schritt in die funktionale Programmierung. Die Mastering von Streams macht deinen Code lesbar wie eine Geschichte, die ihn von dir und anderen wartungsfähiger macht. Am Ende gibt es Übungen, um alles in die Praxis zu setzen.

Für wen ist dieser Kurs geeignet:

Jeder Java-Entwickler, der sich für Streams oder die Funktionale Programmierung im Allgemeinen interessiert. Während der Titel Java 8 (die die introduction war) erwähnt, ist es eine großartige Fertigkeit, egal an welcher Java-Version du arbeitest. Du wirst voraussichtlich ein grundlegendes Verständnis für die Verwendung von Java haben, wie das Kompilieren und die Ausführung von Code sowie das Ausweiten von Kursen und die Implementierung von Schnittstellen.

Die für diesen Kurs benötigten Materialien:

Es sind keine Materialien erforderlich, um diesen Kurs zu folgen. Wenn du die Übungen am Ende jedoch machen möchtest, musst du JDK 8 oder höher installieren. Es ist auch eine Möglichkeit die Java-Dateien zu bearbeiten und zu betreiben, die .java-Dateien sind. Das könnte so einfach sein wie der notepad, aber ich empfehle die Verwendung einer IDE, wie IntelliJ oder Eclipse.That's
ist es!

Triff deine:n Kursleiter:in

Teacher Profile Image

Jeronemo

Kursleiter:in

Hey there, welcome to my profile! I have the classical Dutch name Jeroen, but you may call me Jeronemo.

I've been a backend developer for the good part of a decade, dabbing mostly in microservice architecture using REST, Java & Spring Boot, but having worked with loads of other stuff like ADO, Docker, ELK stack, Eureka, Flyway, Gitlab, GWT, Hazelcast, Hibernate, Hoverfly, IntelliJ, Jackson, Jenkins, JIRA, JSON, Junit, Kubernetes, RabbitMQ, Maven, Mockito, Nexus, SOAP, Sonar, SQL, WDSL, XSD & Zuul.

Vollständiges Profil ansehen

Skills dieses Kurses

Entwicklung Programmiersprachen Java
Level: All Levels

Kursbewertung

Erwartungen erfüllt?
    Voll und ganz!
  • 0%
  • Ja
  • 0%
  • Teils teils
  • 0%
  • Eher nicht
  • 0%

Warum lohnt sich eine Mitgliedschaft bei Skillshare?

Nimm an prämierten Skillshare Original-Kursen teil

Jeder Kurs setzt sich aus kurzen Einheiten und praktischen Übungsprojekten zusammen

Mit deiner Mitgliedschaft unterstützt du die Kursleiter:innen auf Skillshare

Lerne von überall aus

Ob auf dem Weg zur Arbeit, zur Uni oder im Flieger - streame oder lade Kurse herunter mit der Skillshare-App und lerne, wo auch immer du möchtest.

Transkripte

1. Einführung: Hallo zusammen, willkommen in der Klasse Java Eight Streams, eine praktische Einführung. Mein Name ist Geselle, und in diesem Kurs werde ich Ihnen alles über Streams in ihrer Verwendung erzählen . Dieser Kurs zielt darauf ab, zu dosieren, wenn Sie wenig oder keine Erfahrung mit Streams haben ist Gaze, um Ihnen einen Einblick in die Möglichkeit von Streams zu geben . Sie erkennen Situationen , in denen Streams nützlich sein können. Wir werden tiefer in die Nutzung von Streams und deren Breite eintauchen. Sie möchten sie in funktionalen Interfaces und Lambdas verwenden . Ich werde häufig verwendete Operationen für diejenigen erklären , die sich nach einem praktischeren Ansatz sehnen. Dieser Kurs bietet auch Übungen , um das erlernte Wissen in die Praxis umzusetzen. Lass uns anfangen. 2. Stream und Gebrauch Fall: Streams-Nutzung und Anwendungsfall. Wasserströme verwenden einfach gesagt, ein Strom kann verwendet werden, um eine Sammlung von Gegenständen zu verarbeiten. In einem späteren Kapitel werden wir uns eingehender mit einigen der spezifischen Methoden zur Verarbeitung einer Sammlung befassen. Aber im Moment stellen Sie sich die Verarbeitung nur als Filtern, Ändern und Anreichern der Daten für die Sammlung vor. Beachten Sie jedoch, dass Produktionen, die als Input für Streams verwendet werden, von den Streams nicht wirklich geändert werden. Stattdessen erhalten wir durch die Ausführung eines Streams separate Ergebnisse, die von der ursprünglichen Sammlung getrennt sind . Diese Arbeitsschritte sind funktionsbeschreibend geschrieben. Das heißt, ein Stream liest sich wie eine Geschichte, wenn er richtig gemacht wird, was sie so unglaublich nützlich macht. Um dies zu demonstrieren. Hier ist ein Beispiel für eine herkömmliche Methode zum Filtern, Sammeln, Sortieren und Drucken einiger Daten. Ich verwende dieselbe Logik, die in Streams geschrieben wurde. Ich bin mir sicher, dass Sie irgendwann beide Seiten verstehen können , aber ich denke, wir sind uns alle einig, dass die Verwendung von Streams es viel, viel einfacher macht , zu verstehen, was der Code tut. Da hast du es also. Streams werden verwendet, um eine Sammlung von Elementen auf sehr vernünftige Weise zu verarbeiten. Wie funktionieren Streams? Wie bereits erwähnt, arbeiten Streams an einer Sammlung von Gegenständen. Sie haben vielleicht bemerkt, dass die Wortsammlung mit einer Schnittstelle übereinstimmt. Auf Java. Die im Java-Util-Paket gefundene Schnittstelle ist mit der Arbeit mit Streams verknüpft. den meisten Fällen verwenden Sie normalerweise eine Liste oder ein Set, um einen Stream zu starten , der die Collection-Schnittstelle erweitert. Es gibt andere Möglichkeiten , einen Stream zu erstellen. Wir werden in dieser Klasse nicht auf sie eingehen. Sie finden sie in den Ressourcen. Mit der Ankunft von Java Eight eine Standardmethode namens wurde der Collection-Schnittstelle eine Standardmethode namens stream hinzugefügt. Für diejenigen, die mit Standardmethoden nicht vertraut sind. Mit Standardmethoden können Sie den Schnittstellen Ihrer Bibliotheken neue Funktionen hinzufügen und die Binärkompatibilität mit Code sicherstellen , der für ältere Versionen der Schnittstellen geschrieben wurde. Dieser Standardmethodenstream gibt eine Instanz des Streams zurück kostet die zentrale API-Klasse , mit der wir mit ihnen arbeiten können. Nachdem Sie den Stream erstellt haben, können Sie nun Operationen miteinander verketten und den Stream ausführen. Dazu später mehr. Fassen wir zusammen, was wir bisher gelernt haben. Streams werden verwendet, um eine Sammlung von Elementen auf sehr lesbare Weise zu verarbeiten . Streams ändern diese Quellsammlung nicht, sondern erstellen stattdessen ein separates Ergebnis von der ursprünglichen Sammlung getrennt ist. Die Stream-Schnittstelle ist der zentrale API-Preis für die Arbeit mit Streams. Alles, was die Collection-Schnittstelle erweitert oder implementiert , verfügt über eine Standard-Stream-Methode für Interaktion mit der zentralen API-Klasse 3. Funktionale Schnittstellen und Lambda: Funktionale Interfaces und Lambdas. Bevor wir über Stream-Operationen sprechen können, müssen wir über die Voraussetzungen für die Verwendung von Strips sprechen . Die Lambdas. Lambdas sind im Grunde anonyme innere Klassen, deren funktionale Schnittstellen der Java-Compiler implizit die benötigten Informationen angibt. Fangen wir von vorne an. Anonyme innere Klassen. Bei der Implementierung einer Schnittstelle werden Sie alle ihre Methoden implementieren. Hier ist ein Beispiel , in dem Sie eine implementierte Klasse erstellen und instanziieren. Hier haben wir eine Schnittstelle namens my interface with the print. Eine wichtige Methode wird von meiner Schnittstelle implementiert. Aber was ist, wenn ich eine etwas andere Implementierung der Drucke benötige , eine wichtige Methode. In diesem Szenario müsste ich eine andere Klasse erstellen , die meine Schnittstelle implementiert. Schon wieder. Stellen Sie sich vor, wenn Sie zehn verschiedene Varianzen haben, wird es sehr bald überladen. Das ist ein Hinweis auf anonyme innere Klassen. Anonyme innere Klasse ist eine Erweiterung einer Klasse. Eine Implementierung einer Schnittstelle ohne Namen, daher anonym. Wir konzentrieren uns auf den Interface-Teil S. Das ist der wichtige Teil im Kontext von Streams. Da sie keinen Namen haben, können wir keine Instanz der anonymen inneren Klasse alleine erstellen . Stattdessen müssen Sie die anonyme innere Klasse in einem einzigen Ausdruck deklarieren und instanziieren . Dieser Ausdruck sieht wie folgt aus, was folgendermaßen übersetzt wird. Beim Erstellen der anonymen inneren Klassenversion meiner Schnittstelleninformationen. Wie Sie sehen können, haben wir eine Instanz meiner Schnittstelle erstellt , ohne dass eine Klasse benötigt wird, die das Interface implementiert. Und wenn ich eine neue Implementierung meiner Schnittstelle hinzufügen möchte, kann ich das einfach tun. Da haben wir es. Anonyme innere Klassen können verwendet werden, um eine Schnittstelle zu implementieren , ohne dass eine starre Klasse definiert werden muss. Sie können sie einfach im laufenden Betrieb erstellen. Funktionale Schnittstellen. funktionale Schnittstelle ist nur eine Schnittstelle außer dass sie nur eine einzige Methode enthält , die implementiert werden muss. Jede Schnittstelle, die diese Kriterien erfüllt, ist eine funktionale Schnittstelle. Genau wie unser Beispiel für mein Interface gerade. Obwohl dies nicht erforderlich ist, können Sie die Anmerkung zur funktionalen Schnittstelle hinzufügen , um Ihre Absicht zu verdeutlichen. Als zusätzlichen Bonus gibt der Compiler eine Ausnahmekompilierungszeit aus, wenn es sich bei Verwendung dieser Annotation nicht wirklich um eine funktionale Schnittstelle wirklich um eine funktionale Schnittstelle handelt. Gehen wir die gängigsten Funktionsschnittstellen durch bei der Arbeit mit Streams verwendet werden. erste ist der Lieferant mit zugelassenen bekommt. Es erwartet keine Argumente, gibt aber etwas zurück. Der Lieferant liefert Ihnen etwas, normalerweise ein neues, leeres, sauberes Objekt. Man könnte es als Fabrik sehen. Das nächste ist das Prädikat. Mit zugelassen. Es erwartet ein Argument, wertet es aus und gibt einen booleschen Wert zurück. Wie der Name schon sagt, ist es im Grunde ein Test. Erfüllt das Argument t die angegebenen Kriterien ja oder nein? Verbraucher mit seinen Methoden akzeptiert, akzeptiert ein Argument, macht etwas damit, gibt aber nichts zurück verbraucht dabei buchstäblich die Argumente. Der Fahrradkonsument tut dasselbe wie der Verbraucher, außer dass er zwei Argumente erwartet. Funktion mit ihren Methoden gelten. Erwartet ein Argument, es macht etwas damit. Und Rückgaben in Argumenten bilden im Grunde das Argument im Prozess ab oder reichern es an, das Argument r und t können dieselbe Klasse sein. Die Funktion by macht dasselbe wie die Funktion. Excepted erwartet zwei Argumente, T und U machen etwas mit ihnen. Ich bin Returns sind genau wie die Funktion. Argumente können bei Bedarf dieselbe Klasse sein. Und in diesem Sinne kommen wir zur letzten gemeinsamen Funktionsschnittstelle. Binärer Operator. Der binäre Operator ist eine Erweiterung von by function, wobei T , U und R genau dieselbe Klasse sind. Stellen Sie sicher, dass Sie ein gutes Verständnis der funktionalen Schnittstellen im Allgemeinen und der gängigen Schnittstellen haben der funktionalen Schnittstellen , bevor Sie fortfahren. Es wird Ihnen helfen, Lambdas und Stream-Operationen leichter zu verstehen . Lambda-Ausdrücke. Am deutlichsten sind anonyme innere Klassen funktionaler Schnittstellen, von denen der Java-Compiler implizit die benötigten Informationen kennt. Wir wissen jetzt, was eine anonyme innere Klasse ist und wie wir noch alle Methoden einer Schnittstelle implementieren müssen . Wir stellen fest, dass funktionale Schnittstellen reguläre Schnittstellen sind, außer dass sie nur eine einzige Methode haben , die implementiert werden muss. Da eine funktionale Schnittstelle nur eine einzige Methode hat, ist der Compiler in der Lage, viele Informationen basierend auf dem Kontext zu verstehen . Sie als Entwickler können diese Informationen weglassen. Lässt den Compiler also wissen, dass Sie Dinge auslassen. Die Lambda-Syntaxprobleme. Wir beginnen mit einer unregelmäßigen anonymen inneren Klasse und wandeln sie Stück für Stück in einen ausgewachsenen Lambda-Ausdruck um . Oder verwenden Sie das Prädikat der funktionalen Schnittstelle, um zu testen, ob eine angegebene Ganzzahl höher als eins ist. das Gleichheitszeichen kümmerten, ist uns der Name der Schnittstelle aufgefallen, die wir implementieren. Der Hauptteil der anonymen inneren Klasse, die Methodensignatur und der Hauptteil der Methoden, die wir implementieren. Schauen Sie sich den Schnittstellennamen und die Methodensignatur genauer an. Siehst du, wie der Compiler auf dieses Wissen schließen könnte? Beachten Sie, dass sich die Schnittstellennamen bereits auf der linken Seite der equal-Anweisungen befinden. Beachten Sie, dass, da das Prädikat eine funktionale Schnittstelle ist, nur eine einzige Methode implementiert werden muss. Wir wissen also bereits, welche Methoden wir implementieren. Beide Arten von Informationen können vom Compiler abgeleitet werden. Unser erster Schritt besteht darin, dies mit der zusammengefassten Syntax, dem Pfeil, zu schreiben . Damit. Wir werden den Schnittstellennamen und den Methodennamen loswerden. Das sieht schon viel sauberer aus, oder? Hier sehen wir die Eingabe der Methoden, die Ganzzahl auf der linken Seite des Pfeils und den Hauptteil der Methode auf der rechten Seite. Aber es gibt immer noch einige Informationen wir in diesem Fall auslassen können. Da es eine einzige Methode gibt und der Compiler deren Signatur kennt , kann der Compiler den Eingabetyp aus dem Kontext ableiten. Die Klammern um die Eingänge sind ebenfalls verschwunden. Dies ist nur möglich, weil es sich um einen einzelnen Parameter handelt. Falls Sie zwei oder mehr haben, sind die Klammern obligatorisch. Es gibt noch eine Sache, auf die wir jetzt schließen können. Es hat mit dem Körper und der Rückgabeerklärung zu tun. Im Fall einer einzigen Codezeile im Hauptteil des Verfahrens kann der Compiler daraus schließen, dass diese Codezeile tatsächlich die Rückgabeanweisung des Körpers ist. Mit diesem letzten Schritt haben wir den ausgewachsenen Lambda-Ausdruck erreicht. Sie werden die ganze Zeit sehen, wenn Sie mit Strings arbeiten. Eigentlich gibt es eine Möglichkeit, das Lambda noch kürzer zu schreiben. In einigen Fällen. Dies wird als Methodenreferenz bezeichnet. Aber ich schlage vor, es selbst nachzuschlagen, wenn Sie ein gutes Verständnis für lange Tuns im Allgemeinen haben. Eine letzte wichtige Sache, die bei Lumped Us zu erwähnen ist, ist, dass die in ihnen verwendeten lokalen Variablen endgültig oder effektiv endgültig sein sollten. Tatsächlich bedeutet final eine Variable , die nicht das endgültige Schlüsselwort hat, aber ihr Wert ändert sich nicht, nachdem sie zum ersten Mal zugewiesen wurde. Der Grund dafür ist, dass es sich bei Lumped Us im Grunde genommen um einen Code handelt , den Sie mit anderen Methoden ausführen können. wie Sie unser Prädikat an eine Filteroperation innerhalb einer Zeichenfolge übergeben können . Aus diesem Grund muss Java eine Kopie der lokalen Variablen erstellen , die in der Lunge verwendet werden soll. Um Parallelitätsprobleme zu vermeiden. Das Alpha hat beschlossen, lokale Variablen vollständig einzuschränken. Fassen wir zusammen, was wir bisher gelernt haben. Anonyme innere Klassen sind innere Klassen , die eine Schnittstelle implementieren, ohne einen Namen zu haben, diese einmal deklariert und instanziiert werden müssen. Funktionale Schnittstellen sind regelmäßig Schnittstellen außer dass sie nur eine einzige Methode enthalten , die implementiert werden muss. Die Annotation der funktionalen Schnittstelle kann verwendet werden, um diese Regel durchzusetzen, ist nicht erforderlich. Lumped us sind anonyme innere Klassen funktionaler Schnittstellen, von denen der Java-Compiler anhand des Kontextes auf fehlende Informationen schließen kann . Wir wissen jetzt, wie man einen Lambda-Ausdruck und eine unregelmäßige anonyme innere Klasse erzeugt einen Lambda-Ausdruck und . Und schließlich müssen lokale Variablen, die in Lumped Us verwendet werden, endgültig oder effektiv in Ordnung sein. 4. Stream: In den nächsten Kapiteln werde ich häufig verwendete Operationen an Strings erläutern. Aber zuerst sollten wir über die beiden Arten möglicher Operationen sprechen , Zwischen- und Terminaloperationen. Ein Stream wird nur vollständig ausgeführt, wenn eine Terminaloperation verwendet wird. Daher endet ein Stream immer in einem Terminalbetrieb und kann nur einen davon in einem Stream haben. Zwischenoperationen sind alle Operationen bevor wir den endgültigen Terminalbetrieb erreichen. Zwischenoperationen geben eine Instanz von Stream zurück, wodurch es möglich ist, sie alle miteinander zu verketten. Da alle Zwischenoperationen stream zurückgeben, können Sie eine Zeichenfolge ohne Terminaloperationen in einer Variablen speichern . Vielen Dank noch heute, damit Sie Ihrem Stream tatsächlich Schritte hinzufügen können , die auf externen Einflüssen basieren, z. B. einem anderen Filter oder einer anderen Art der Datenanreicherung. Achten Sie jedoch darauf, obwohl Sie Zwischenoperationen in Variablen speichern können , ist es nicht möglich, denselben Stream zweimal mit einer Terminaloperation auszuführen . Der Compiler erkennt dies nicht, aber Sie erhalten während der Laufzeit eine Ausnahme wie diese. Noch einmal. Zwischenoperationen geben einen Stream zurück und können daher verknüpft und in Variablen gespeichert werden. Zwischenoperationen allein führen keinen Stream aus. Eine Terminaloperation führt den vollständigen Stream aus und gibt einen anderen Wert als einen Stream zurück. Ein Stream kann nur einmal mit einer Terminaloperation ausgeführt werden . zweimaliger Versuch führt während der Laufzeit zu einer Ausnahme. Mit diesem Wissen gehen wir zu den häufig verwendeten Operationen über. 5. Intermediate Operation: Filter: Fangen wir mit den Grundlagen an. Filtern. Filter ist eine Zwischenoperation, mit der Sie Objekte aus Strings herausfiltern können Objekte aus Strings herausfiltern , die den angegebenen Test nicht bestehen. Sie könnten den Zwischenoperationsfilter als das Stream-Äquivalent einer if-Anweisung sehen. Eingabe ist ein Prädikat das, wie wir gelernt haben, ein Objekt empfängt, einen Test darauf durchführt und wahr oder falsch zurückgibt, wahr oder falsch zurückgibt je nachdem, ob es den Test bestanden hat oder nicht. Hier ist ein Beispiel für seine Verwendung. Und mach dir keine Sorgen um die anderen Operationen. Wir werden bald zu denen kommen. In diesem Beispiel verwenden wir Filter, um den Stream nur mit Objekten fortzusetzen den Stream nur mit Objekten , deren Liste der Telefonnummern leer ist. Bevor Sie zu den verbleibenden Kunden als Liste zurückkehren, können Sie anhand eines beliebigen endgültigen Werts filtern. Hier filtern wir basierend auf unserer lokalen Variablen, z. B. können wir sie auch mit mehreren Filtern hintereinander verketten . Die Filteroperation ist ein Paradebeispiel dafür, wie Streams Ihren Code lesbarer machen. Vor allem, wenn Sie lange Zeit in einem solchen Wert gespeichert haben. Sie können jetzt auf einen Blick sehen, wonach wir filtern. 6. Terminal fürJede: Unser erster Terminalbetrieb für jeden. Das forEach ist eine sehr einfache Terminalbedienung. Es wird verwendet, um eine bestimmte Aktion für alle Elemente im Stream auszuführen . Unter der Annahme, dass die Elemente im Prozess, seine Eingaben, ein Verbraucher sind. Es nimmt also ein Objekt, macht etwas damit, gibt aber keinen Wert zurück. Danach. Wir haben seine Implementierung in der zuvor diskutierten Operation gesehen, aber hier ist sie noch einmal. In diesem Beispiel drucken wir den Vornamen jeder Kundenbranche. Denken Sie daran, dass für jedes Element nur dann gearbeitet wird, wenn sie den Rest des Streams durchlaufen haben . Wenn wir also vor dem Terminalbetrieb einen Filter setzen , erhalten nur Kunden mit weniger als drei Geräten ihren Vornamen, drucken ihn aus mit weniger als drei Geräten . Wusste sie schließlich, dass normale Methoden auch in einem Klumpen angewendet werden können? Nehmen Sie diese Methode, z. B. sieht das für Sie nicht wie eine Verbraucherimplementierung aus? Es akzeptiert ein einzelnes Objekt, macht etwas damit, gibt aber danach keinen Wert zurück. Und in der Tat können wir diese Methode in unserem forEach verwenden, um sie dabei lesbarer zu machen. Und das war's. Für jeden führt einfach eine angegebene Aktion für jedes Element des Streams , das den Rest des Streams durchläuft. 7. Zwischenbetrieb: Karte: Eine weitere grundlegende Zwischenoperation, Map. Map ist eine Zwischenoperation, die häufig verwendet wird, um von einem Objekttyp auf einen anderen zuzuordnen. Es wird jedoch in der Regel auch zur Ausführung von Geschäftslogik verwendet. Seine Eingaben sind eine Funktion, die, wie wir jetzt wissen, ein Objekt der Klasse a nimmt, etwas damit macht und ein Objekt der Klasse b zurückgibt , wobei Klausel a und B dieselbe Klasse sein können. Hier ist ein Beispiel, in dem wir von Klasse A nach B abbilden. Hier haben wir ein Kundenobjekt als Eingabe. Wir ordnen das einer Zeichenfolge zu, die aus seinem Vor- und Nachnamen besteht , bevor wir es ausdrucken. In diesem Fall ordnen wir eine Zuordnung von Klasse A zu Klasse B, von Kunde zu String. In diesem nächsten Beispiel haben wir ein Kundenobjekt als Eingabe bei der Arbeit mobil auf ihre Geräte. Geben Sie dann dasselbe Kundenobjekt zurück und bereichern Sie Ihr Objekt effektiv. In diesem Fall kartieren wir von Kunde zu Kunde und erreichen das Objekt auf dem Weg dorthin. Beachten Sie, dass ich, da der Lambda-Text zwei Anweisungen enthält, die Klammern hinzufügen und das Schlüsselwort zurückgeben musste. Schließlich ist es, genau wie bei jeder Zwischenoperation, möglich, mehrere mathematische Operationen innerhalb desselben Streams zu haben . 8. Zwischenbetrieb: flatMap: Als nächstes FlatMap. Wie der Name schon sagt, ähnelt FlatMap Map. Es handelt sich um eine Zwischenoperation, die üblicherweise verwendet wird, um von einem Objekttyp zu einem anderen zuzuordnen. Mit dem Unterschied, dass FlatMap mit Eins-zu-Viele-Beziehungen arbeitet. Eingabe ist ebenfalls eine Funktion, aber dem Rückgabeobjekt wird eine Einschränkung auferlegt. Ein Stream sollte zurückgegeben werden. Hier sehen wir die Methodensignatur von map und flatMap nebeneinander, um Ihnen den Unterschied zu zeigen. Während beide die Funktion erwarten, erwartet FlatMap, dass der r-Wert vom Typ string ist. Schauen wir uns an, was es macht und wie es sich davon unterscheidet. In unseren Beispielen haben wir das Kundenobjekt verwendet, das eine Liste von Geräten enthält. Was würde Ihrer Meinung nach passieren, wenn wir die Kartenoperation verwenden würden , um jeden Kunden auf seine Geräte umzustellen? Wie Sie in der Ausgabe sehen können, Zuordnung von einem Kunden zu einer Geräteliste führt die Zuordnung von einem Kunden zu einer Geräteliste zu einem Stream von Gerätelisten. Beim Ausdrucken werden diese Listen nacheinander gedruckt. Dies könnte etwas sein, das Sie für Ihren funktionalen Anwendungsfall benötigen . den meisten Fällen interessieren Sie sich jedoch In den meisten Fällen interessieren Sie sich jedoch für alle separaten Geräte nicht für separate Gerätelisten. Hier kommt FlatMap ins Spiel. Wie schon gesagt. Flatmap legt eine Einschränkung das Rückgabeobjekt der Funktion fest. Sie können sehen, dass sich das Lambda für FlatMap leicht geändert hat und jetzt das Gerät als Stream zurückgibt. Statt als Liste. Beachten Sie in den Ausgängen , dass die Geräte jetzt einzeln gedruckt werden , anstatt Liste für Liste. Der Schlüssel dabei ist, dass FlatMap Streams als Ergebnisse erwartet , die dann wieder zu einem einzigen Stream zusammengeflacht werden. Noch einmal zusammen. Sie können jetzt deutlich den Unterschied zwischen der Map- und FlatMap-Operation erkennen . Zusammenfassend sollten Maps verwendet werden, wenn Objekte mit einer Eins-zu-Eins-Beziehung konvertiert werden. Dabei sollte FlatMap beim Konvertieren von Objekten mit einer Eins-zu-Viele-Beziehung verwendet werden. Bei Verwendung von FlatMap ist der Rückgabewert ein Stream von Objekten. 9. Zwischenoperationen: sequentiell und parallel: Zwei Operationen derselben Münze, sequentiell und parallel. Sequentiell und parallel sind beide Zwischenoperationen , die den gesamten Stream sequentiell bzw. parallel machen . Da es sich um Zwischenoperationen handelt, können sie zusammen sogar mehrmals zum Stream hinzugefügt werden . Es spielt keine Rolle, wo im Stream die Operation platziert wird. Der gesamte Stream ist entweder sequentiell oder parallel. Nicht ein bisschen von beidem. Denken Sie daran, dass die letzte sequentielle oder parallele Operation Industrie erwähnte, die Industrie erwähnte, diejenige, die tatsächlich verwendet wird. Das bedeutet, dass dieser Stream genau der gleiche ist wie dieser Stream. Ein Stream ist standardmäßig sequenziell, was bedeutet, dass die Elemente in der Reihenfolge ausgeführt werden, in der sie in der US-Sammlung erscheinen. Das bedeutet auch, dass diese Streams die gleiche Ausgabe haben . Wie du siehst. Dies führt dazu, dass eins bis zehn in der Reihenfolge mit oder ohne sequentielle Operation ausgedruckt werden. Wenn wir das jedoch auf parallel ändern, erhalten wir, wie Sie sehen können, jedes Mal, wenn wir den Stream ausführen, ein anderes Ergebnis. Der Stream wird mit mehreren Threads ausgeführt, was bedeutet, dass die geleistete Arbeit auf verschiedene Ausführungen aufgeteilt wird . Die sogenannten Bedrohungen. Beachten Sie, dass das Parallellaufen eines Streams nicht automatisch bedeutet, dass der Stream threadsicher ausgeführt werden kann. Sie als Entwickler müssen sicherstellen, dass Ihr Code genauso funktioniert, 1236 oder welche Bedrohungen auch immer. Da will es nicht. Eine weitere Sache, die Sie beim parallelen Ausführen von Dingen beachten sollten , ist, dass dies nicht unbedingt bedeutet, dass die Arbeit schneller erledigt wird. etwas mit mehreren Threads erstellen , müssen Sie die Arbeit in Teile aufteilen für jedes Teil eine Ausführung erstellen. Delegierte Arbeit, die verschiedenen Ergebnisse zu einem zusammenführen. Dies führt in unserem Fall zu einem gewissen Mehraufwand beim Ausführen des Codes oder Streams, was nur dann von Vorteil wenn Sie genügend Elemente in Ihrem Stream haben oder wenn Ihr Stream sehr rechenintensiv ist. Zusammenfassend lässt sich sagen, dass Sie mit den sequentiellen und parallelen Operationen den gesamten Stream schnell sequentiell oder parallel gestalten können . einen Stream parallel ausführen, müssen Sie als Entwickler sicherstellen, dass der Code threadsicher ist. 10. Zwischenbetrieb: Blick auf die: Gehen wir mit einem einfachen, bevor wir zu den komplexen übergehen. Pq. Pq ist eine Zwischenoperation , mit der Sie beim Ausführen einer Zeichenfolge buchstäblich einen Blick hinter die Kulissen werfen können . Seine Hauptanwendung ist das Debuggen und Protokollieren seiner Eingaben. Als Verbraucher bedeutet dies, dass es einen Wert erhält und etwas damit macht , ohne dass es einen Rückgabewert gibt. Während es möglich ist, Daten innerhalb des Spitzenbetriebs zu ändern , gehen Sie dabei ein Risiko ein. Abhängig von Ihrer Java-Version und davon, ob Ihr Terminalbetrieb die Objekte in der Zeichenfolge verarbeiten muss oder nicht. Der Code in Peek kann ausgeführt werden oder nicht. Seien Sie sehr vorsichtig , wenn Sie peak für andere Zwecke als Debugging und Protokollierung verwenden . Hier ist ein Beispiel für seine Verwendung. In diesem Beispiel verwenden wir peak, um einen Namen eines Geräts zu drucken , bevor wir es weiterhin seinen Bestelldetails zuordnen diese potenzielle Weiterverarbeitung sammeln. Ein Ergebnis dieses Streams ist eine Liste von Bestelldetails. Dank des Spitzenbetriebs können wir mit einem Gerät, das Objekte für die Ergebnisse verwenden, einige Protokollierung erhalten . Und ich habe gesehen, dass Peak einfach eine Möglichkeit ist , während eines Streams etwas Protokollierung zu erhalten. Sie können damit Daten ändern, aber es ist riskant, daher würde ich davon abraten wenn Sie mit Streams noch nicht vertraut sind. 11. Endabschnitt: sammeln: Unser zweiter Terminalbetrieb, Collect. Collect ist ein Terminalvorgang, der alle Elemente eines Streams in etwas sammelt. Es wird häufig verwendet, um die resultierenden Elemente eines Streams in eine Liste aufzunehmen. Es gibt zwei Implementierungen für diese. Die erste erwartet eine Implementierung der Collector-Schnittstelle. Dies ist jedoch keine funktionale Schnittstelle und kann daher nicht als Lambda-Ausdruck umgeschrieben werden. Zum Glück für uns, ja, Lava war so nett, den Sammlerclustern alle möglichen hilfreichen Methoden zur Verfügung den Sammlerclustern alle möglichen zu stellen. Viele davon sprengen den Rahmen dieses Workshops. Aber es gibt eine, die Sie häufig verwenden, Collectors mit zwei Listen. Wie Sie vielleicht erwarten. Dies gibt eine Implementierung der Collector-Schnittstelle zurück, alle Elemente der Zeichenfolge in einer Liste sammelt und zurückgibt. Ich persönlich benutze dies 190, 9% der Fälle, in denen ich etwas sammeln muss , und erwarte , dass Sie dasselbe erleben. Aber um zu verstehen, was es ein bisschen besser macht, gehen wir die zweite Implementierung durch. Dieser erwartet einen Lieferanten und zwei von Verbrauchern. Das Java-Dokument gibt uns einen schönen Überblick darüber, was es tut. Der Lieferant liefert uns das, was wir als Ergebnis des Sammelvorgangs erwarten. Dann wird der erste Fahrradverbraucher verwendet, um ein Element des Streams in dieses Ergebnis zu konsumieren. Dies wird fortgesetzt, bis alle Elemente aus dem Stream oder bis zum Endergebnis verbraucht werden. Dies zeigt uns nicht, was der zweite Bi-Verbraucher tut, der es kombiniert, aber das liegt daran, dass der Combiner nur benötigt wird, wenn der Stream parallel ausgeführt wird. In diesem Fall haben Sie möglicherweise zwei oder mehr Threads, die mit dem Lieferanten beginnen. Nachdem alle Bedrohungen ausgeführt wurden, müssen die Ergebnisse dieser Threads zu einem einzigen Ergebnis kombiniert werden einem einzigen Ergebnis kombiniert Genau dafür wird ein Combiner verwendet. Lassen Sie es uns in die Praxis umsetzen. Mit einem Lieferanten und zwei von Verbrauchern. Ich werde das Sammeln der Kundenelemente in einem Stream replizieren . Wir beginnen mit dem Lieferanten. Bei Aufrufen wird die leere Liste angezeigt, in die wir alle Elemente des Streams einfügen. Als nächstes brauchen wir einen Fahrradverbraucher, alle Elemente der Saite in der Lieferliste sammelt . Dies macht deutlich, dass unser Ergebnis tatsächlich diese Liste ist und dass alle Kundenelemente aus dem Stream in einer Setlist zusammengefasst werden. Im Falle eines sequenziellen Streams das das Ende. Um jedoch eine parallele Verarbeitung zu ermöglichen, wird ein Endprodukt des Verbrauchers benötigt , das zwei Ergebnisse zu einem kombiniert. dies vom Verbraucher verwenden, fügen wir die Elemente des zweiten Ergebnisses in das erste hinzu. Dies wird vom Stream wiederholt, bis alle Bedrohungsergebnisse wieder zu einem zusammengeführt sind. Hier werden sie in den Sammelvorgang eingefüllt. Und damit wissen Sie, wie Sie Ihre eigenen Sammlungen erstellen können. Um es noch einmal zu wiederholen: Es gibt zwei Implementierungen der Collect-Zusammenarbeit. Der erste erwartet einen Collector, von dem Java mithilfe der Collectors-Klausel einige Optionen für Sie vorbereitet hat . Der zweite erwartet einen Lieferanten und bindet die Verbraucher, wodurch er viel anpassbarer wird. Du wirst die meiste Zeit die vorbereitete Klasse zum Sammeln dieser Klasse verwenden . Aber zumindest weißt du jetzt, wie es funktioniert. 12. Endablauf: Reduzieren: Der Endbetreiber wird die Reduzierung besprechen. Reduce ist eine Terminaloperation, mit der alle Elemente eines Streams in ein einzelnes Objekt reduziert werden können . Es ist ein bisschen wie eine Sammeloperation, die wir besprochen haben. Aber wohingegen collect alle Elemente des Streams auf unveränderliche Container wie eine Liste oder ein Set anwendet . Reduce sammelt nicht alle Elemente, sondern wendet sie auf ein einzelnes Objekt an. Die Identität. Reduzieren, nimmt seine Identität, Akkumulation oder Elemente in die Identität kombiniert dann mehrere Ergebnisse zu einem, falls sie parallel ausgeführt werden. Reduzieren ist die am schwersten zu greifende Operation. Fühl dich also nicht schlecht, wenn du nicht alles auf einmal bekommst. Nehmen Sie sich Zeit, um diesem Abschnitt zu folgen und probieren Sie die Übungen am Ende des Unterrichts aus. Wenn Sie noch Fragen haben, können Sie diese gerne über die Plattform stellen. Ordnung, lass uns eintauchen. Deep reduce erwartet einen Startwert namens Identitätsfunktion, der als Akkumulation verwendet wird, und einen binären Operator verwendet wird, um Ergebnisse aus separaten Threads zu kombinieren. Der Alpha-Hund gibt uns einen schönen Überblick darüber, was er tut. Diese Identität gibt uns den Anfang der Ergebnisse. Es sollte eine saubere, leere Tafel sein, sodass das Hinzufügen eines Werts aus dem Stream zu dieser Identität zu diesem Ergebnis führt und sich als Produkt ändert. Dann wird es für jedes Element aus dem Stream mithilfe der Funktion by in den resultierenden Wert akkumuliert . Genau wie beim Sammeln zeigt uns dies nicht, was der binäre Operator, der Combiner, tut. Das gleiche gilt hier. Der Combiner wird nur verwendet , um die Ergebnisse mehrerer Threads miteinander zu kombinieren mehrerer Threads miteinander falls der Stream parallel ausgeführt wird. Lassen Sie es uns in die Praxis umsetzen. In unserem Beispiel wählen wir alle Kunden in einer Ganzzahl aus, wählen wir alle Kunden in einer Ganzzahl die die Gesamtanzahl der Geräte darstellt , die diesen Kunden gehören. Unsere Identität sollte eine Ganzzahl sein. Infolgedessen wollen wir aus diesem Stream raus. Was den Wert angeht. Denken Sie daran, dass das Hinzufügen eines Ergebnisses zur Identität zu einer Änderung als Produkt führen muss. In unserem Fall müssen wir die Größe aller Gerätelisten addieren aller Gerätelisten um zu unseren Endergebnissen zu gelangen. Welcher Wert der Identität bedeutet, dass Identität plus Größe der Geräteliste gleich zwei ist. Das Gerät ist , stimmt, Null. Unsere Identität wird also so sein. Als nächstes benötigen wir eine Funktion, die ein Element des Streams in diese Identität erzeugt. Das erste generische Element, das in der Funktion by verwendet wird, ist eine Ganzzahl, die den aktuellen Wert der Ergebnisse darstellt . Die Zwischensumme, wenn man so will. Die zweite generische Verwendung ist das Element des Streams, das in die Zwischensumme reduziert wird. Die dritte generische Verwendung ist der Typ des Ergebnisses der Operation, eine Ganzzahl. Dieses dritte Generikum muss mit dem ersten identisch sein, was logisch ist, da der erste generische Begriff die Zwischensumme darstellt. Im Falle eines sequentiellen Streams wäre das das Ende. Um jedoch eine parallele Verarbeitung zu ermöglichen, müssen Sie einen binären Operator verwenden, um zwei Ergebnisse zu einem zu kombinieren. Mit diesem binären Operator kombinieren wir die Ergebnisse von zwei Threads miteinander. Dies wird vom Stream wiederholt, bis alle Thread-Ergebnisse wieder zu einem zusammengeführt sind. Hier werden sie in den Reduziervorgang eingefüllt. Um es noch einmal zu wiederholen, beginnen wir mit einer sauberen, leeren Tafel als Identity Zero. In unserem Fall. Wir fügen dann die Größe der Geräteliste aller Elemente aus dem Stream zu dieser Identität hinzu. Wenn der Stream parallel ausgeführt wird, kombinieren wir sie, um zwei Zwischensummen zu einer zu addieren , bis wir ein einziges Ergebnis übrig haben. In unserem Beispiel haben wir unsere komplexen Objekte auf eine einzige Ganzzahl reduziert . Aber reduced kann auch verwendet werden, um alle Elemente eines Streams in ein einziges komplexes Objekt zu reduzieren . Zum Beispiel könnten wir unsere Kunden auf einen einzigen Kunden reduzieren , der unsere Informationen enthält. Aber ich lasse das als Teil der Übungen, die du alleine machen kannst. 13. Zusammenfassung und Afterword: Wir sind am Ende dieses Kurses angelangt. Lassen Sie uns zusammenfassen, um zu sehen, was wir auf unserer Reise in die Java Eight Streams API gelernt haben . Wir haben angefangen zu lernen, wofür Streams verwendet werden und wie sie funktionieren. Wir haben dann aufgeschlüsselt, wie Sie dank funktionaler Schnittstellen einen Lambda-Ausdruck aus einer anonymen inneren Klasse erstellen können einen Lambda-Ausdruck aus einer anonymen inneren Klasse erstellen . Wir haben kurz besprochen, aber funktionale Schnittstellen sind es und welche Sie häufig bei der Arbeit mit Streams verwenden. Schließlich gingen wir auf häufig verwendete Zwischen - und Terminaloperationen ein. Danke, dass du dir diesen Kurs angesehen hast. Ich hoffe, Sie haben genug über Streams gelernt, um Situationen zu erkennen , in denen Sie sie verwenden können und können. Wenn Sie mir helfen möchten, diesen Kurs zu verbessern und uns mitzuteilen, ob Sie ihn nützlich fanden oder nicht. Ich wäre Ihnen dankbar, wenn Sie eine Bewertung abgeben würden. Wie versprochen. Ich habe einige Übungen für Sie vorbereitet, um zu sehen, ob Sie das in diesem Kurs erlernte Wissen anwenden können . Jede Übung hat eine Anfrage, ein erwartetes Ergebnis, damit Sie überprüfen können, ob Sie es richtig gemacht haben. Wenn es Unklarheiten über diese bereits angebotenen Übungen gibt, können Sie mir gerne eine Nachricht mit Ihren Fragen senden. Ich helfe Ihnen nach besten Kräften. Noch einmal. Danke fürs Zuschauen und bis zum nächsten Mal.