Ich habe mit Java 8 Lambdas herumgespielt, um Sammlungen einfach zu filtern. Ich habe jedoch keinen präzisen Weg gefunden, um das Ergebnis als neue Liste innerhalb derselben Anweisung abzurufen. Hier ist mein bisher prägnantester Ansatz:
List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);
Beispiele im Internet haben meine Frage nicht beantwortet, da sie aufhören, ohne eine neue Ergebnisliste zu erstellen. Es muss einen prägnanteren Weg geben. Ich hätte erwartet , dass, dass die Stream
Klasse hat Methoden toList()
, toSet()
...
Gibt es eine Möglichkeit, die Variablen targetLongList
direkt durch die dritte Zeile zuzuweisen?
collections
lambda
java-8
java-stream
Daniel K.
quelle
quelle
sourceLongList
später nicht brauchen, gibt esCollection.removeIf(…)
für die Bequemlichkeit.List<Long> targetLongList = sourceLongList.stream().collect(Collectors.toList());
Antworten:
Was Sie tun, ist möglicherweise der einfachste Weg, vorausgesetzt, Ihr Stream bleibt sequentiell - andernfalls müssen Sie vorher sequential () aufrufen
forEach
.[spätere Bearbeitung: Der Grund für den Aufruf von sequential () ist, dass der Code in seiner
forEach(targetLongList::add)
jetzigen Form ( ) rassig wäre, wenn der Stream parallel wäre. Selbst dann wird der beabsichtigte Effekt nicht erreicht, da diesforEach
explizit nicht deterministisch ist - selbst in einem sequentiellen Stream ist die Reihenfolge der Elementverarbeitung nicht garantiert. Sie müssten verwendenforEachOrdered
, um die korrekte Bestellung sicherzustellen. Die Absicht der Stream-API-Designer ist, dass Sie in dieser Situation den Collector verwenden (siehe unten).]Eine Alternative ist
quelle
toList
. Dazu setzen Sie Folgendes unter die Importe der Datei :static import java.util.stream.Collectors.toList;
. Dann liest der Sammelruf gerade.collect(toList())
.Collectors
Klasse unter Einstellungen -> Java -> Editor -> Inhaltsassistent -> Favoriten hinzu . Danach müssen Sie nur nochtoLi
bei gedrückter Strg + Leertaste eingeben , damit die IDE ausgefüllttoList
und der statische Import hinzugefügt wird.IntStream
einige andere, aber nicht ganz andere MethodenStream
nicht vorhanden sindcollect(Collector)
und Sie sie aufrufen müssenIntStream.boxed()
, um sie zuerst in eine reguläre zu konvertierenStream
. Andererseits möchten Sie vielleicht nurtoArray()
.sequential()
vorforEach
oder Verwendung ‚forEachOrdered`Aktualisiert:
Ein anderer Ansatz ist zu verwenden
Collectors.toList
:Vorherige Lösung:
Ein anderer Ansatz ist zu verwenden
Collectors.toCollection
:quelle
Collectors::toList
Javadoc: "Es gibt keine Garantien für den Typ, die Veränderlichkeit, die Serialisierbarkeit oder die Thread-Sicherheit der zurückgegebenen Liste. Wenn mehr Kontrolle über die zurückgegebene Liste erforderlich ist, verwenden SietoCollection(Supplier)
."Ich verwende gerne eine util-Methode, die einen Kollektor zurückgibt,
ArrayList
wenn ich dies möchte.Ich denke, die verwendete Lösung
Collectors.toCollection(ArrayList::new)
ist für eine so häufige Operation etwas zu laut.Beispiel:
Mit dieser Antwort möchte ich auch zeigen, wie einfach es ist, benutzerdefinierte Kollektoren zu erstellen und zu verwenden, was im Allgemeinen sehr nützlich ist.
quelle
toList
wenn Sie beispielsweise die Liste später im Programm ändern möchten. In dertoList
Dokumentation heißt es: "Es gibt keine Garantien für den Typ, die Veränderlichkeit, die Serialisierbarkeit oder die Thread-Sicherheit der zurückgegebenen Liste. Wenn mehr Kontrolle über die zurückgegebene Liste erforderlich ist, verwenden SietoCollection
." . Meine Antwort zeigt einen Weg, dies in einem häufigen Fall bequemer zu machen.Wenn Sie über ein Array von Grundelementen verfügen, können Sie die in Eclipse- Sammlungen verfügbaren Grundelement-Sammlungen verwenden .
Wenn Sie die sourceLongList nicht ändern können von
List
:Wenn Sie verwenden möchten
LongStream
:Hinweis: Ich bin ein Mitarbeiter von Eclipse Collections.
quelle
Ein wenig effizienter Weg (vermeiden Sie das Erstellen der Quellliste und das automatische Entpacken durch den Filter):
quelle
Dies ist der Aufruf, mit dem Sie jeden Stream in List konvertieren können.
konkreter:
von:
https://www.geeksforgeeks.org/collectors-tolist-method-in-java-with-examples/
quelle
Wenn es Ihnen nichts ausmacht, Bibliotheken von Drittanbietern zu verwenden, enthält die Cyclops-React- Bibliothek von AOL (Offenlegung, an der ich beteiligt bin) Erweiterungen für alle JDK-Sammlungstypen , einschließlich List . Die ListX-Schnittstelle erweitert java.util.List und fügt eine große Anzahl nützlicher Operatoren hinzu, einschließlich Filter.
Sie können einfach schreiben-
ListX kann auch aus einer vorhandenen Liste erstellt werden (über ListX.fromIterable).
quelle
Es gibt eine andere Variante der Sammelmethode, die von der LongStream-Klasse und in ähnlicher Weise auch von den IntStream- und DoubleStream-Klassen bereitgestellt wird.
Führt eine veränderbare Reduktionsoperation für die Elemente dieses Streams durch. Eine veränderbare Verkleinerung ist eine Verkleinerung, bei der der reduzierte Wert ein veränderbarer Ergebniscontainer ist, z. B. eine ArrayList, und Elemente durch Aktualisieren des Ergebnisstatus und nicht durch Ersetzen des Ergebnisses eingefügt werden. Dies ergibt ein Ergebnis, das entspricht:
Wie beim Reduzieren (long, LongBinaryOperator) können Erfassungsvorgänge parallelisiert werden, ohne dass eine zusätzliche Synchronisierung erforderlich ist. Dies ist eine Terminaloperation.
Die Antwort auf Ihre Frage mit dieser Erhebungsmethode lautet wie folgt:
Unten ist die Methodenreferenzvariante aufgeführt, die ziemlich intelligent ist, aber einige, die schwer zu verstehen sind:
Unten wird die HashSet-Variante sein:
Ähnlich sieht die LinkedList-Variante aus:
quelle
Falls jemand (wie ich) da draußen nach Wegen sucht, mit Objekten umzugehen, anstatt mit primitiven Typen, dann benutze sie
mapToObj()
Drucke:
quelle
quelle
Hier ist Code von AbacusUtil
Offenlegung: Ich bin der Entwickler von AbacusUtil.
quelle
com.landawn.abacus.util.stream.LongStream
oderLongStreamEx
in AbacusUtilSie können den Code wie folgt umschreiben:
quelle
So sammeln Sie in einer veränderlichen Liste:
So sammeln Sie in einer unveränderlichen Liste:
Erklärung von
collect
aus dem JavaDoc :quelle
Wenn Sie dies nicht verwenden
parallel()
, funktioniert diesquelle
collect
den Rückgabewert aufzurufen und dann nicht zu speichern. In diesem Fall könnten SieforEach
stattdessen verwenden. Aber das ist immer noch eine schlechte Lösung.