491 Stimmen

Abrufen einer Liste aus einem java.util.stream.Stream in Java 8

Ich habe mit Java 8 Lambdas herumgespielt, um Kollektionen einfach zu filtern. Aber ich habe keinen prägnanten Weg gefunden, um das Ergebnis in Form einer neuen Liste im selben Statement abzurufen. Hier ist mein bisher prägnantester Ansatz:

List sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);

Beispiele im Netz haben meine Frage nicht beantwortet, weil sie ohne Erzeugung einer neuen Ergebnisliste enden. Es muss einen prägnanteren Weg geben. Ich hätte erwartet, dass die Stream-Klasse Methoden wie toList(), toSet(), ... hat.

Gibt es einen Weg, wie die Variable targetLongList direkt in der dritten Zeile zugewiesen werden kann?

663voto

Maurice Naftalin Punkte 10126

Was du tust, mag der einfachste Weg sein, vorausgesetzt, dein Stream bleibt sequenziell—ansonsten musst du einen Aufruf von sequential() vor forEach setzen.

[spätere Bearbeitung: Der Grund, warum der Aufruf von sequential() notwendig ist, liegt darin, dass der Code in seiner aktuellen Form (forEach(targetLongList::add)) bei einem parallel laufenden Stream ein Wettlaufzustand wäre. Selbst dann wird er nicht den beabsichtigten Effekt erzielen, da forEach explizit nichtdeterministisch ist—sogar in einem sequenziellen Stream ist die Reihenfolge der Elementverarbeitung nicht garantiert. Du müsstest forEachOrdered verwenden, um die richtige Reihenfolge sicherzustellen. Die Absicht der Stream-API-Designer ist, dass du in dieser Situation einen Collector verwendest, wie unten dargestellt.]

Ein Alternativvorschlag ist

targetLongList = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(Collectors.toList());

194voto

MohamedSanaulla Punkte 5942

Aktualisiert:

Ein weiterer Ansatz besteht darin, Collectors.toList zu verwenden:

targetLongList = 
    sourceLongList.stream().
    filter(l -> l > 100).
    collect(Collectors.toList());

Frühere Lösung:

Ein weiterer Ansatz besteht darin, Collectors.toCollection zu verwenden:

targetLongList = 
    sourceLongList.stream().
    filter(l -> l > 100).
    collect(Collectors.toCollection(ArrayList::new));

13voto

Lii Punkte 10698

Ich verwende gerne eine Hilfsmethode, die einen Collector für ArrayList zurückgibt, wenn ich das möchte.

Ich finde die Lösung mit Collectors.toCollection(ArrayList::new) etwas zu laut für eine so häufige Operation.

Beispiel:

ArrayList result = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(toArrayList());

public static  Collector> toArrayList() {
    return Collectors.toCollection(ArrayList::new);
}

Mit dieser Antwort möchte ich auch zeigen, wie einfach es ist, benutzerdefinierte Collector zu erstellen und zu verwenden, was im Allgemeinen sehr nützlich ist.

11voto

ZhekaKozlov Punkte 32454

Es gibt eine neue Methode [Stream.toList()](https://download.java.net/java/early_access/jdk16/docs/api/java.base/java/util/stream/Stream.html#toList()) in Java 16:

List targetLongList = sourceLongList
         .stream()
         .filter(l -> l > 100)
         .toList();

6voto

Pramod Punkte 377
    stream.collect(Collectors.toList());

Dies ist der Aufruf, den Sie verwenden können, um einen beliebigen Stream in eine List umzuwandeln.

konkreter:

    List myList = stream.collect(Collectors.toList()); 

aus:

https://www.geeksforgeeks.org/collectors-tolist-method-in-java-with-examples/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X