Sucht nach dem ersten element durch das Prädikat
Ich habe gerade angefangen zu spielen mit Java 8 lambdas und ich bin zu versuchen, einige der Dinge, die ich verwendet, um in funktionalen Sprachen.
Zum Beispiel, die meisten funktionalen Sprachen haben eine Art von find-Funktion, die arbeitet auf Sequenzen oder Listen, gibt das erste element, für das das Prädikat true
. Der einzige Weg, ich kann sehen, dies zu erreichen in Java 8 ist:
lst.stream()
.filter(x -> x > 5)
.findFirst()
Aber es scheint ineffizient zu mir, als die filter scannt die gesamte Liste, zumindest nach meinem Verständnis (und das kann falsch sein). Gibt es einen besseren Weg?
Es ist nicht ineffizient, Java 8 Stream-Implementierung lazy ausgewertet, so dass filter wird nur angewendet, um die terminal-Betrieb. Gleiche Frage hier: stackoverflow.com/questions/21219667/stream-and-lazy-evaluation
Cool. Das ist, was ich hoffte, es würde tun. Es wäre schon eine große design-flop sonst.
Wenn Ihre Absicht ist, wirklich zu prüfen, ob die Liste enthält so ein element überhaupt (nicht einzelne aus der ersten von möglicherweise mehreren), .findAny() kann theoretisch effizienter sein, in einem parallell-Einstellung, und natürlich kommuniziert, dass die Absicht deutlicher.
Im Vergleich zu einer einfachen forEach-Zyklus, so würde es zu viele Objekte auf dem heap, und Dutzende von dynamischen Methodenaufrufen. Während dies vielleicht nicht immer auf die bottom-line performance-tests, die in den "hot spots" es macht einen Unterschied, zu unterlassen, die triviale Nutzung von Strom und ähnliche Schwergewichts-Konstrukte.
Cool. Das ist, was ich hoffte, es würde tun. Es wäre schon eine große design-flop sonst.
Wenn Ihre Absicht ist, wirklich zu prüfen, ob die Liste enthält so ein element überhaupt (nicht einzelne aus der ersten von möglicherweise mehreren), .findAny() kann theoretisch effizienter sein, in einem parallell-Einstellung, und natürlich kommuniziert, dass die Absicht deutlicher.
Im Vergleich zu einer einfachen forEach-Zyklus, so würde es zu viele Objekte auf dem heap, und Dutzende von dynamischen Methodenaufrufen. Während dies vielleicht nicht immer auf die bottom-line performance-tests, die in den "hot spots" es macht einen Unterschied, zu unterlassen, die triviale Nutzung von Strom und ähnliche Schwergewichts-Konstrukte.
InformationsquelleAutor siki | 2014-05-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nein, filter scannt nicht den gesamten Strom. Es ist ein intermediate-operation, die gibt einen " lazy stream (eigentlich alle zwischen-Operationen wieder ein lazy-stream). Um Sie zu überzeugen, können Sie einfach den folgenden test:
Welche Ausgänge:
Sehen Sie, dass nur die beiden ersten Elemente der stream verarbeitet werden.
So können Sie gehen mit Ihrem Ansatz, das ist völlig in Ordnung.
get();
hier, weil ich weiß, welche Werte ich an der Futter-stream-pipeline, und damit, dass es ein Ergebnis. In der Praxis sollten Sie nicht verwendenget();
, aberorElse()
/orElseGet()
/orElseThrow()
(für eine aussagekräftige Fehlermeldung statt eines NSEE) wie Sie vielleicht nicht wissen, ob die Operationen angewendet, um die stream-pipeline wird das Ergebnis in einem element..findFirst().orElse(null);
zum BeispielVerwenden Sie nicht orElse null. Das sollte ein anti-pattern. Es ist alles enthalten in den Optionalen, also warum sollte man riskieren, eine NPE? Ich denke, der Umgang mit Optional ist der bessere Weg. Testen Sie einfach die Optional mit isPresent (), bevor Sie es verwenden.
InformationsquelleAutor Alexis C.
Nein ist es nicht - es wird "Pause", sobald das erste element der Befriedigung des Prädikats gefunden wird. Lesen Sie mehr über die Faulheit in der stream Paket javadoc, insbesondere (Hervorhebung von mir):
InformationsquelleAutor wha'eve'
Musste ich herausfiltern, die nur ein Objekt aus einer Liste von Objekten. So habe ich diese, hoffe, es hilft.
InformationsquelleAutor CodeShadow
Neben Alexis C's Antwort, Wenn Sie arbeiten mit einem array-Liste, in denen Sie sich nicht sicher sind, ob das element, das Sie suchen, existiert, verwenden Sie dieses.
Dann könnte man einfach prüfen, ob eine ist
null
.Ich habe Ihren Beitrag bearbeitet. 0 (null) kann ein gültiges Ergebnis, wenn Sie sind auf der Suche in einer Liste von Integer-zahlen. Ersetzt Variablentyp Integer-und Standardwert von null.
InformationsquelleAutor Ifesinachi Bryan
Wenn Sie auf der Suche für einen boolean-Wert zurückgeben, können wir es besser machen, durch hinzufügen von null-check:
InformationsquelleAutor shreedhar bhat
Es sei denn, deine Liste ist wirklich riesig (Tausende von Elementen), Verwendung von streams, hier ist nur teuer und macht sogar den code härter zu verstehen.
Hinweis: java ist KEINE funktionale Sprache (und jvm ist nicht besonders geeignet für die Implementierung von funktionalen Sprachen effizient).
Viel einfacher und mehr effektiv ist (ist auf alle Durchsuchbar):
Oder, wenn Sie wollen, überspringen Sie den iterator:
Tatsächlich, ich Frage mich wirklich, warum so viele Menschen vorschlagen, diese komplexe und teure streams Maschinen, sogar für triviale Dinge wie immer das erste element eines Arrays. (ja: arrays werden immer noch unterstützt, in Java8).
"und jvm ist nicht besonders geeignet für die Implementierung von funktionalen Sprachen effizient)" 🙂 Haben Sie gehört, über Clojure?
Auf was für ein Unsinn ist deine Antwort?
Ich Stimme Ihnen vollkommen zu, dass die Verwendung von streams in einem so einfachen Fall macht den code weniger lesbar. Streams sind oft langsamer als standard-loops, nie schneller, und oft schwieriger zu verstehen.
InformationsquelleAutor Enrico 'nekrad' Weigelt