Lassen Sie mich mit dem allgemeinen Punkt beginnen, dass die Java-Sprachspezifikation der Implementierung von Streams nur wenige Einschränkungen auferlegt. Es ist also wirklich nicht sinnvoll, nach der Leistung von Java-Streams zu fragen: Es wird zwischen Implementierungen sehr unterschiedlich sein.
Beachten Sie auch, dass Stream
eine Schnittstelle ist. Sie können Ihre eigene Klasse erstellen, die Stream
implementiert, um eine beliebige Leistung oder ein spezielles Verhalten für sorted
, die Sie möchten, zu haben. Die Frage nach der Leistung von Stream
macht also selbst im Rahmen einer Implementierung keinen Sinn. Die OpenJDK-Implementierung verfügt über viele Klassen, die die Schnittstelle Stream
implementieren.
Wenn wir uns die OpenJDK-Implementierung anschauen, die Sortierung von Streams endet in der SortedOps
-Klasse (siehe Quelle here), werden Sie feststellen, dass die Sortiermethoden am Ende Erweiterungen von Stateful-Operationen zurückgeben. Zum Beispiel:
private static final class OfInt extends IntPipeline.StatefulOp<Integer>
überprüfen Diese Methoden, wenn der stromaufwärts bereits in denen sortiert Fall, dass sie es nur auf den nachgelagerten passieren. Sie haben auch spezielle Ausnahmen für sortierte Streams (d. H. Upstream), die die Arrays vorsortieren, die sie am Ende sortieren, was die Effizienz verbessert (über eine SpinedBuffer
, die sie für Streams unbekannter Größe verwenden). Aber wenn der Upstream nicht bereits sortiert ist, akzeptieren sie alle Elemente, sortieren sie dann und senden sie an die Methode accept
der Downstream-Instanz.
Die Schlussfolgerung daraus ist, dass die OpenJDK sorted
Implementierung alle Elemente sammelt, sortiert und dann sendet nach unten. In einigen Fällen wird dies Ressourcen verschwenden, wenn der Downstream einige Elemente verwerfen wird. Es steht Ihnen frei, eine eigene spezielle Sortieroperation zu implementieren, die für Sonderfälle effizienter ist.Der einfachste Weg ist die Implementierung einer Collector
, die eine Liste der n größten oder kleinsten Elemente im Stream enthält. Ihr Betrieb könnte dann in etwa so aussehen:
.collect(new CollectNthLargest(4)).stream()
Um
.sorted().limit(4)
Der gesamte Stream ist sortiert. –
Es hängt von den Eigenschaften dieses Stromes ab; Wenn der zugrunde liegende 'Spliterator' meldet, dass der Stream 'SORTED' ist, dann ist' sort() 'ein No-Op; ansonsten wird, wie bereits erwähnt, der gesamte Stream sortiert, was bedeutet, dass alle vom Stream erzeugten Elemente vor Beginn der Sortierung entnommen werden müssen - und das ist nur logisch – fge
@fge ... aber ... darüber nachzudenken ... gibt es Algorithmen, die die kleinsten k Elemente eines 'N' Elements unsortierte Liste in' O (N) 'erhalten. http://stackoverflow.com/questions/5380568/algorithm-to-find-k-smallest-numbers-in-array-of-n-items. Es sollte möglich sein, den Algorithmus für Java 8-Streams zu implementieren, allerdings nicht so, wie das OP es versucht. –