1 / 219

Informatik 2 Datenstrukturen

Informatik 2 Datenstrukturen. Prof. Dr.-Ing. Holger Vogelsang holger.vogelsang@hs-karlsruhe.de. Inhaltsverzeichnis. Abstrakte Datentypen (3) Datenstrukturen in Java (11) Elementare Datenstrukturen (14) Iteratoren (32) Streams (48) Hashtabellen (57) Bäume (103) Graphen (192).

wind
Download Presentation

Informatik 2 Datenstrukturen

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Informatik 2Datenstrukturen Prof. Dr.-Ing. Holger Vogelsang holger.vogelsang@hs-karlsruhe.de

  2. Inhaltsverzeichnis • Abstrakte Datentypen (3) • Datenstrukturen in Java (11) • Elementare Datenstrukturen (14) • Iteratoren (32) • Streams (48) • Hashtabellen (57) • Bäume (103) • Graphen (192) Informatik 2 - Datenstrukturen

  3. Abstrakte Datentypen Übersicht Grafische Oberflä- chen Übersicht Layouts Ereignisse Widgets Grafik- operationen Grafik- widgets Effekte, Animationen Offene Punkte Daten- strukturen ADTs Datenstrukturen in Java Elementare Datenstrukturen Iteratoren, Stream Hash- tabellen Bäume Graphen Typinfo., I/O Annota- tionen Ein-, Ausgabe Laufzeit- typinfo. Entwurf Prinzipien Verbindung von Modulen Spring OSGi Informatik 2 - Datenstrukturen

  4. Abstrakte Datentypen Übersicht • Bisher: • Einführung in objektorientierte Programmierung • Einfache Datenstrukturen wie Array, Vektor und Liste • Jetzt: • Festlegung von Schnittstelle und Funktionalität einer Datenstruktur, ohne eine konkrete Implementierung zu verwenden Definition: Abstrakter Datentyp Ein abstrakter Datentyp (ADT) ist ein Datentyp (eine Menge von Werten und eine Sammlung von Operationen auf diesen Werten), der nur über eine Schnittstelle zugänglich ist. Ein ADT kann bei identischer Funktionalität unterschiedliche mögliche Implementierungen besitzen. Informatik 2 - Datenstrukturen

  5. Abstrakte Datentypen Übersicht • Eine ADT-Spezifikation besteht aus einer Signatur und Axiomen (hier stark vereinfacht dargestellt, die mathematischen Begriffe wurden teilweise nicht verwendet). • Signatur ∑ = (S, Ω) mit • S = Die Menge von Datentypen, die der ADT verwendet. Einer der Datentypen wird in der Regel durch den ADT neu definiert. Die anderen existieren bereits. • Ω = Die Menge von Methoden und Konstanten des ADT. • Axiome legen die Semantik und damit das Verhalten des ADT unabhängig von einer konkreten Implementierung fest. • In diesen Unterlagen werden teilweise Beispiele aus dem Buch „Algorithmen und Datenstrukturen“ von Saakeund Sattler übernommen. Die Darstellung der ADTs entspricht auch der Syntax aus dem Buch. Informatik 2 - Datenstrukturen

  6. Abstrakte Datentypen Beispiel: Liste • Unvollständiger ADT für eine Liste List von Elementen des Datentyps T. type List(T) importNat operators [] List _:_ : T  List  List addFirst : List  T  List getFirst : List  T getTail : List  List size : List  Nat axiomsl : List, x : T getTail(addFirst(l, x)) = l getFirst(addFirst(l, x)) = x getFirst(x : l) = x getTail(x : l) = l size([]) = 0 size(x : l) = succ(size(l)) []erzeugt eine neue, leere Liste _:_Konstruktions- vorschrift (neuer Operator) x : lElement x und weitere Listenelemente in l succentstammt ADT für natürliche Zahlen Informatik 2 - Datenstrukturen

  7. Abstrakte Datentypen Beispiel: Liste • Mögliche Listen: • [] leere Liste • 1 : [] Liste mit dem Element 1 • 1 : 2 : 3 : 4 : [] Liste mit den Elementen 1 bis 4 • Deutlich erkennbar: Das Wissen über die konkrete Implementierung der Liste ist für die Anwendung nicht erforderlich. • In einer Programmiersprache: Schnittstelle der Klasse (öffentliche Methoden und Datentypen) sowie die Dokumentation des Verhalten sind erforderlich. • Die Art der Implementierung ist unwichtig (sofern sie das Laufzeitverhalten nicht beeinflusst). • Wozu dient das Wissen über ADTs? • ADT könnte in Java eine Schnittstelle (ein interface) sein. • Die konkrete Implementierung implementiert die Schnittstelle. • Es lässt sich prima „auf der Schnittstelle“ arbeiten. Informatik 2 - Datenstrukturen

  8. Abstrakte Datentypen Anwendung eines ADT Beispiel ADT List und konkrete Java-Umsetzung der Operatoren type List(T) importNat operators [] List _:_ : T  List  List addFirst: List  T  List getFirst : List  T getTail : List  List size: List  Nat axiomsl : List, x : T getTail(addFirst(l, x)) = l getFirst(addFirst(l, x)) = x getFirst(x : l) = x getTail(x : l) = l size([]) = 0 size(x : l) = succ(size(l)) T: class <<interface>> List +add(int i, e: T): boolean +get(index: int): T +remove(index: int): T +size(): int T: class T: class LinkedList ArrayList +add(int i, e: T): boolean +get(index: int): T +remove(index: int): T +size(): int +add(int i, e: T): boolean +get(index: int): T +remove(index: int): T +size(): int Vektor Verkettete Liste Informatik 2 - Datenstrukturen

  9. Abstrakte Datentypen Anwendung eines ADT Beispiel ADT List und konkrete Java-Umsetzung der Axiome type List(T) importNat operators [] List _:_ : T  List  List addFirst: List  T  List getFirst : List  T getTail : List  List size: List  Nat axiomsl : List, x : T getTail(addFirst(l, x)) = l getFirst(addFirst(l, x)) = x getFirst(x : l) = x getTail(x : l) = l size([]) = 0 size(x : l) = succ(size(l)) z.B. als Dokumentation oder zur Validierung einer Implementierung Informatik 2 - Datenstrukturen

  10. Abstrakte Datentypen ADT: Beschreibung der Axiome • Die Axiome können durch nahezu beliebige „Sprachen“ beschrieben werden. • Komplexere Aussagen sind z.B. mit OCaml (funktionale Programmiersprache, siehe http://caml.inria.fr/) möglich  soll hier nicht näher vertieft werden. Informatik 2 - Datenstrukturen

  11. Datenstrukturen in Java Übersicht Grafische Oberflä- chen Übersicht Layouts Ereignisse Widgets Grafik- operationen Grafik- widgets Effekte, Animationen Offene Punkte Daten- strukturen ADTs Datenstrukturen in Java Elementare Datenstrukturen Iteratoren, Stream Hash- tabellen Bäume Graphen Typinfo., I/O Annota- tionen Ein-, Ausgabe Laufzeit- typinfo. Entwurf Prinzipien Verbindung von Modulen Spring OSGi Informatik 2 - Datenstrukturen

  12. Datenstrukturen in JavaÜbersicht • Vereinfachte Übersicht über die Collections-Klassen in Java Informatik 2 - Datenstrukturen

  13. Datenstrukturen in JavaSchnittstellen • Iterable<E>: Über die Datenstruktur kann direkt iteriert werden  siehe Iteratoren. • Collection<E>: Gruppe von Elementen, Duplikate können erlaubt sein • List<E>: Collection mit einer Ordnung, Indexzugriff ist erlaubt (möglicherweise ineffizient) • RandomAccess: Leere Schnittstelle, der Indexzugriff ist mit konstanter Zeit möglich. • Queue<E>: spezielle Queue-Operationen vorhanden • Deque<E>: Queue mit Einfüge- und Löschoperationen an Anfang und Ende • Set<E>: Menge von Elementen ohne Duplikate • SortedSet<E>: Menge mit einer Totalordnung der Elemente (anhand ihrer natürlichen Ordnung oder anhand eines Vergleichs-Objektes) • NavigableSet<E>: SortedSet mit Methoden, um kleinere oder größere Elemente zu finden • Map<K,V>: Bildet Schlüssel-Objekte (K) auf Werte (V) ab. • SortedMap<K,V>: Eine Map mit einer Totalordnung der Elemente • NavigableMap<K,V>: SortedMapmit Methoden, um kleinere oder größere Schlüssel zu finden. Informatik 2 - Datenstrukturen

  14. Elementare Datenstrukturen Übersicht Grafische Oberflä- chen Übersicht Layouts Ereignisse Widgets Grafik- operationen Grafik- widgets Effekte, Animationen Offene Punkte Daten- strukturen ADTs Datenstrukturen in Java Elementare Datenstrukturen Iteratoren, Stream Hash- tabellen Bäume Graphen Typinfo., I/O Annota- tionen Ein-, Ausgabe Laufzeit- typinfo. Entwurf Prinzipien Verbindung von Modulen Spring OSGi Informatik 2 - Datenstrukturen

  15. Elementare DatenstrukturenÜbersicht in Java • Elementare Datenstrukturen Informatik 2 - Datenstrukturen

  16. Elementare DatenstrukturenVektor – Prinzip • Die Klassen ArrayList<E> und Vector<E> verwalten dynamisch beliebig viele Objekte. • Die Anordnung der Objekte erfolgt sequentiell. • Die interne Implementierung erfolgt durch ein Array. • Der Vektor besitzt eine Referenz auf den Speicherbereich. • Ein Vektor eignet sich besonders für einen schnellen freien Zugriff über Indizes auf die Elemente. • Der Indexzugriff erfolgt immer geprüft. • Vector ist im Gegensatz zu ArrayList thread-sicher und damit langsamer. E: class ArrayList ArrayList size -values[*]: E -size: int Extra Platz 0 1 2 3 4 5 6 7 Informatik 2 - Datenstrukturen

  17. Elementare DatenstrukturenBeispiel zu ArrayList • Beispiel: importjava.util.ArrayList; publicclassArrayListTest { publicstaticvoidmain(String[] args) { ArrayList<Integer> contents = newArrayList<>(10); for(int i = 0; i < 10; i++) { contents.add(i * i); } int v = contents.get(12); // Geprüfter Zugriff --> // Abfangen der Fehler System.out.println(contents.size()); System.out.println(contents.contains(2)); } } Informatik 2 - Datenstrukturen

  18. Elementare DatenstrukturenArrayList und Vektor in Java • Beide implementieren RandomAccess: Indexzugriff in konstanter Zeit Informatik 2 - Datenstrukturen

  19. Elementare Datenstrukturen Vektor – Aufwandsabschätzungen Aufwandsabschätzungen für die Vektor-Klassen Informatik 2 - Datenstrukturen

  20. Elementare DatenstrukturenListe: Prinzip • Prinzip einer einfach verketteten Liste: • Die Liste besitzt einen Kopf und ein Ende. • Jeder Listeneintrag verweist auf seinen Nachfolger. • Jeder Listeneintrag beinhaltet die Nutzdaten. LinkedList last Listelement Listelement Listelement first value value value E: class E: class first 0, 1 LinkedList Listelement 0, 1 next -value: E last 0, 1 Informatik 2 - Datenstrukturen

  21. Elementare DatenstrukturenListe: Prinzip • Prinzip einer doppelt verketteten Liste: • Die Liste besitzt einen Kopf und ein Ende. • Jeder Listeneintrag verweist auf seinen Nachfolger und Vorgänger • Jeder Listeneintrag beinhaltet die Nutzdaten. LinkedList last Listelement Listelement Listelement first value value value E: class E: class first 0, 1 LinkedList Listelement 0, 1 next -value: E last 0, 1 0, 1 prev Informatik 2 - Datenstrukturen

  22. Elementare DatenstrukturenListe in Java • LinkedList implementiert nicht RandomAccess: Indexzugriff nicht in konstanter Zeit! Informatik 2 - Datenstrukturen

  23. Elementare DatenstrukturenListe – Aufwandsabschätzung Informatik 2 - Datenstrukturen

  24. Elementare Datenstrukturen Queue – Prinzip • Prinzip einer Queue (Warteschlange): • Daten werden in einer Queue am Ende mit offereingetragen und am Anfang der Queue mit pollentfernt  Warteschlange (häufig auch push/pop). • Es gibt einige Container-Klassen, die Queue-Funktionalität einsetzen. Beispiel: LinkedList. • Einsatzgebiete • einfaches Nachrichtensystem (Nachricht ablegen = offer, Nachricht abholen = poll). • allgemeine asynchrone Kommunikation zwischen Auftragnehmer und Auftraggeber Queue 0 1 2 3 Informatik 2 - Datenstrukturen

  25. Elementare DatenstrukturenQueue in Java • LinkedList implementiert Queue Informatik 2 - Datenstrukturen

  26. Elementare Datenstrukturen Queue in Java • Die Methoden gibt es doppelt (aus Queue und Deque): Informatik 2 - Datenstrukturen

  27. Elementare Datenstrukturen Queue – Prinzip • Arbeitsweise einer Queue an einem Beispiel. • Initialzustand: • offer(E4): • poll(): Queue E2 E1 E3 0 1 2 Queue offer E4 E2 E1 E3 0 1 2 3 Queue poll E4 E2 E3 0 1 2 Informatik 2 - Datenstrukturen

  28. Elementare Datenstrukturen Stack – Prinzip • Prinzip eines Stacks (Stapel): • Daten werden in einem Stack am Ende mit offereingetragen und ebenfalls am Ende mit pollentfernt  Stapel(häufig auch push/pop). • Einsatzgebiete u.a.: • Zwischenspeicherung von Objekten, wenn eine Rekursion zu einer Iteration aufgelöst wird. • Text-Parser. Stack 0 1 2 3 Informatik 2 - Datenstrukturen

  29. Elementare DatenstrukturenStack in Java • Es gibt eine Stack-Klasse, die aber nicht optimal ist. Besser: Klasse, dieDequeimplementiert. Informatik 2 - Datenstrukturen

  30. Elementare DatenstrukturenStackin Java • Die Methoden gibt es doppelt (aus Queue und Deque): Informatik 2 - Datenstrukturen

  31. Elementare Datenstrukturen Stack – Prinzip • Arbeitsweise eines Stacks an einem Beispiel. • Initialzustand: • offer(E4): • pollLast(): Stack E2 E1 E3 0 1 2 Stack offer E4 E2 E1 E3 0 1 2 3 Stack pollLast E3 E1 E2 0 1 2 Informatik 2 - Datenstrukturen

  32. Iteratoren Übersicht Grafische Oberflä- chen Übersicht Layouts Ereignisse Widgets Grafik- operationen Grafik- widgets Effekte, Animationen Offene Punkte Daten- strukturen ADTs Datenstrukturen in Java Elementare Datenstrukturen Iteratoren, Stream Hash- tabellen Bäume Graphen Typinfo., I/O Annota- tionen Ein-, Ausgabe Laufzeit- typinfo. Entwurf Prinzipien Verbindung von Modulen Spring OSGi Informatik 2 - Datenstrukturen

  33. Iteratoren Motivation • Wie lässt sich ein Algorithmus schreiben, der unabhängig von einer konkreten Datenstruktur arbeiten kann? • Wie können beliebig viele Algorithmen quasi parallel eine unbekannte Datenstruktur bearbeiten? Informatik 2 - Datenstrukturen

  34. Iteratoren Konzept • Problem: Bisher werden Listen oder Vektoren durch eine Schleife, die direkt auf die Elemente des Containers zugreift, durchlaufen. Wie kann aber ein Algorithmus unabhängig von der Klasse (dem Container) geschrieben werden? • Ziel: Konstruktion eines Algorithmus unabhängig von der konkreten Klasse (dem Container). • Lösung: Iteratoren dienen als Bindeglied zwischen den Containern und Algorithmen auf Containern  Prinzip „Umkehr der Abhängigkeiten“! • Iteratoren sind abstrakte Datentypen, mit deren Hilfe auf eine Folge von Objekten zugegriffen werden kann. • Ein Iteratorverweist immer auf ein Objekt innerhalb einer Folge von Objekten. • Die Vorlesung behandelt Iteratoren nicht vollständig. Informatik 2 - Datenstrukturen

  35. Iteratoren Konzept • Mögliche Vektor- und Listenimplementierungen mit Sortierung der Elemente. • Mit einem Iterator können alle Elemente in ihrer Sortierreihenfolge besucht werden. ArrayList Extra Platz sequentielles Durchlaufen LinkedList last first sequentielles Durchlaufen Informatik 2 - Datenstrukturen

  36. Iteratoren Konzept • Iterator als Bindeglied zwischen Algorithmus und Datenstruktur: ArrayList Zugriff erzeugt Zugriff auf die Datenstruktur über eine einheitliche Schnittstelle Algorithmus erzeugt Zugriff first last LinkedList Informatik 2 - Datenstrukturen

  37. Iteratoren Funktionsweise • Jede Datenstruktur bietet eigene Iteratoren, die eine der beiden folgenden Schnittstellen implementieren: normaler Iterator, um eine Collection vom Anfang bis zum Ende zu durchlaufen • Iterator, um eine Listvorwärts und rückwärts zu • durchlaufen • erlaubt das Ersetzen von Elementen • ermöglicht das Auslesen des aktuellen Indexes Informatik 2 - Datenstrukturen

  38. Iteratoren Funktionsweise • Jede Datenstruktur hat Methoden, die die Iteratorobjekteerzeugen: Informatik 2 - Datenstrukturen

  39. importjava.util.ArrayList; importjava.util.Iterator; importjava.util.ListIterator; publicclassIteratorTest{ publicstaticvoidprint( Iterator<?> iter) { while(iter.hasNext()) { System.out.println(iter.next()); } } publicstatic <E> voidmodify( ListIterator<? super E> iter, E value) { while(iter.hasNext()) { iter.next(); iter.set(value); } } publicstaticvoidmain( String[] args) { ArrayList<String> source= newArrayList<>(); source.add("Hallo 1"); source.add("Hallo 2"); source.add("Hallo 3"); source.add("Hallo 4"); print(source.iterator()); modify(source.listIterator(), "----"); } } Iteratoren Beispiel Informatik 2 - Datenstrukturen

  40. importjava.util.ArrayList; importjava.util.Iterator; importjava.util.ListIterator; publicclassIteratorTest { publicstatic <E> voidcopy( ListIterator<? super E> dest, ListIterator<? extends E> source) { while(source.hasNext()) { // Im Ziel überschreiben? if(dest.hasNext()) { dest.next(); dest.set(source.next()); } // Anhängen, da Ziel kürzer else{ dest.add(source.next()); } } } publicstaticvoidmain( String[] args) { ArrayList<String> source = newArrayList<>(); source.add("Hallo 1"); source.add("Hallo 2"); source.add("Hallo 3"); source.add("Hallo 4"); ArrayList<String> dest = newArrayList<>(); copy(dest.listIterator(), source.listIterator()); } } Iteratoren Weiteres Beispiel kopiert von ArrayList in ArrayList Informatik 2 - Datenstrukturen

  41. copyarbeitet auch mit LinkedList, Vector, und anderen Datentypen. publicstaticvoidmain( String[] args) { LinkedList<String> source = newLinkedList<>(); source.add("Hallo 1"); source.add("Hallo 2"); source.add("Hallo 3"); source.add("Hallo 4"); LinkedList<String> dest = newLinkedList<>(); copy(dest.listIterator(), source.listIterator()); } } copy kann auch zwischen unterschiedlichen Containern kopieren. publicstaticvoidmain( String[] args) { ArrayList<String> source = newArrayList<>(); source.add("Hallo 1"); source.add("Hallo 2"); source.add("Hallo 3"); source.add("Hallo 4"); LinkedList<String> dest = newLinkedList<>(); copy(dest.listIterator(), source.listIterator()); } } Iteratoren Weiteres Beispiel – Variante 2 Im SDK wird aber eher mit Collection und List statt mit Iteratoren gearbeitet. Informatik 2 - Datenstrukturen

  42. Iteratoren Bedeutung von Iteratoren: Beispiel • Die folgenden Klassen verwalten ein einfaches Dateisystem direkt im Hauptspeicher des Computers. File Directory 0..* subdirectories -name: String -access: int -name: String -access: int -contents: byte[*] files 0..* parent 0, 1 // Eine Datei im Dateisystem publicclassFile { private String name; // Name private intaccess; // Rechte private byte[] contents; // Inhalt public File(String name, intaccess, byte[] contents){} public boolean equals( Object other){} // } // Verzeichnis im Dateisystem publicclassDirectory { private String name; private Directory parent; // Vater private LinkedList<Directory> subdirectories; private LinkedList<File> files; private intaccess; // } Informatik 2 - Datenstrukturen

  43. Iteratoren Bedeutung von Iteratoren: Beispiel • Es ergibt sich ein Baum aus Verzeichnissen, in denen jeweils eine Anzahl von Dateien liegen kann. • Ziel: Schreiben einiger Methoden der Directory-Klasse, die über Iteratoren auf den Baum zugreifen. Zählen aller Dateien • Methode der Klasse Directory, die die Anzahl der Dateien in dem Verzeichnis sowie seinen Unterverzeichnissen ermittelt. public intcountFiles() { intsize = files.size(); for (Iterator<Directory> iter = subdirectories.iterator(); iter.hasNext();) { Directory currentDirectory = iter.next(); size += currentDirectory.countFiles(); } returnsize; } Informatik 2 - Datenstrukturen

  44. Iteratoren Bedeutung von Iteratoren: Beispiel Suchen einer Datei • Methode der Klasse Directory, die nur in diesem Verzeichnis (nicht in seinen Unterverzeichnissen) eine Datei sucht. Doppelte Dateinamen kommen nicht vor. public booleancontainsFile(File file) { for (Iterator<File> iter = files.iterator(); iter.hasNext(); ) { if (iter.next().equals(file)) { return true; } } return false; } Informatik 2 - Datenstrukturen

  45. Iteratoren Bedeutung von Iteratoren • Abstrakte Zugriffe auf Datenstrukturen (nicht auf konkrete Collection-Klassen): • Iteratoren • Methoden der Schnittstellen List und Collection • Viele Algorithmen sind auch als statische Methoden in der Klasse Collections vorhanden (sortieren usw.). • Diese arbeiten fast immer auf den Schnittstellen List und Collection. Informatik 2 - Datenstrukturen

  46. Iteratoren Eine Auswahl an Algorithmen der Klasse Collections Informatik 2 - Datenstrukturen

  47. Iteratoren Eine Auswahl an Algorithmen der Klasse Collections Informatik 2 - Datenstrukturen

  48. Streams Motivation • Mit Iteratoren lassen sich Datenstrukturen durchlaufen. Geht das auch eleganter? • Wie kann das Durchlaufen von den Aktionen auf den einzelnen Elementen entkoppelt werden? • Wie lassen sich Datenstrukturen parallel effizienter bearbeiten  nicht Bestandteil dieser Vorlesung. Informatik 2 - Datenstrukturen

  49. Streams Motivation • Zur Erinnerung: Durchlaufen einer Datenstruktur mit Hilfe von Iteratoren, Beispiel: for (Iterator<String> iter = names.iterator(); iter.hasNext(); ) { System.out.println(iter.next()); } • Beispiel zur Summation aller positiven Werte: int sum = 0; for (Iterator<Integer> iter = values.iterator(); iter.hasNext(); ) { int value = iter.next(); if (value > 0) { sum += iter.next(); } } • Es zeigt sich ein immer wiederkehrendes Muster: • äußere Schleife zum Durchlaufen • innerhalb der Schleife mit dem eigentlichen Code • Problem: Große Datenstrukturen werden immer sequentiell abgearbeitet, obwohl im Computer vielleicht einige Prozessorkerne nichts zu tun haben. • Die Stream-API übernimmt das Durchlaufen der Collection-Klassen und Anwenden der Funktionen auf die einzelnen Elemente. Informatik 2 - Datenstrukturen

  50. StreamsEinführung • Was bietet die Stream-API? • Filtern von Werten (z.B. nur Strings einer bestimmten Länge auswählen) • Abbilden von Daten eins Typs auf andere Typen (z.B. automatisch die Kundennummer aus einem Kundenobjekt auslesen) • Begrenzung der Elemente (z.B. nur die ersten 100 Elemente berücksichtigen) • Sortierung der Elemente beim Auslesen • Reduktions-Operationen wie z.B. Summenbildung, erstes Element mit einer bestimmten Bedingung suchen, … • Und vieles mehr, was aus Zeitgründen hier entfällt. • Die übergebenen Funktionen sind Lambda-Ausdrücke. • Ablauf: • Die Collections-Klassen besitzen eine Methode stream, um einen Stream zu erzeugen. Datenstruktur Funktion1 Funktion2 Funktion3 Ergebnis Informatik 2 - Datenstrukturen

More Related