Sammeln Sie einen Java-Stream in eine unveränderliche Sammlung
1. Einführung
In diesem kurzen Artikel werden verschiedene Möglichkeiten zum Sammeln von JavaStreamsbis unveränderlichenCollections –untersucht, die einen speziellen Ansatz erfordern, da StandardCollectorsnur mit veränderlichen Datenstrukturen arbeiten.
2. Maven-Abhängigkeit
Wir werden die Guava-Bibliothek von Google verwenden, um einige unserer Beispiele voranzutreiben:
com.google.guava
guava
22.0
Wir können die neueste Version dieser Abhängigkeit vonhere erhalten.
3. Verwenden voncollectingAndThen() von Java
DiecollectingAndThen()-Methode aus derCollectors-Klasse von Java akzeptiertCollector undfinisherFunction, die auf das vonCollector: zurückgegebene Ergebnis angewendet werden
@Test
public void whenUsingCollectingToImmutableList_thenSuccess() {
List givenList = Arrays.asList("a", "b", "c");
List result = givenList.stream()
.collect(collectingAndThen(toList(), ImmutableList::copyOf));
System.out.println(result.getClass());
}
Da wir die toCollection() Collector nicht direkt, verwenden können, müssen wir Elemente in einer temporären Liste sammeln und daraus eine unveränderliche Liste erstellen.
In diesem Beispiel konvertieren wir einStream in einList mit dem KollektortoList() und erstellen dann einImmutableList. DasImmutableList ist Teil der Guava-Bibliothek. Wenn wir die Ausgabe in der Konsole protokollieren, erhalten wir die Klasse des Basiswerts
Wenn wir die Ausgabe in der Konsole protokollieren, erhalten wir die Klasse der zugrunde liegenden Implementierung vonList:
class com.google.common.collect.RegularImmutableList
4. Verwenden von GuavasCollectors
Beginnend mit Guava 21 enthält jede unveränderliche Klasse ein zugehörigesCollector, das genauso einfach zu verwenden ist wie StandardCollectors:
@Test
public void whenCollectToImmutableList_thenSuccess() {
List list = IntStream.range(0, 9)
.boxed()
.collect(ImmutableList.toImmutableList());
}
Die resultierende Instanz istRegularImmutableList:
class com.google.common.collect.RegularImmutableList
5. Erstellen eines benutzerdefinierten Sammlers
Gehen wir jetzt noch einen Schritt weiter und implementieren unsere benutzerdefiniertenCollector. Um dieses Ziel zu erreichen, verwenden wir die statischeCollector.of()-Methode:
public static Collector, List> toImmutableList() {
return Collector.of(ArrayList::new, List::add,
(left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableList);
}
Weitere Informationen zum Implementieren von benutzerdefiniertenCollectors finden Sie in Abschnitt 4 vonthis article. Und das ist es. Die obige Methode ist Teil unserer benutzerdefinierten Klasse
Wir können es jetzt wie jedes andere integrierteCollectors verwenden:
@Test
public void whenCollectToMyImmutableListCollector_thenSuccess() {
List givenList = Arrays.asList("a", "b", "c", "d");
List result = givenList.stream()
.collect(MyImmutableListCollector.toImmutableList());
}
Lassen Sie uns abschließend die Ausgabe überprüfen:
class java.util.Collections$UnmodifiableRandomAccessList
5.1. MyImmutableListCollector generisch machen
Unsere Implementierung hat eine Einschränkung: Sie gibt immer eine unveränderliche Instanz zurück, die durchArrayList unterstützt wird. Mit einer leichten Verbesserung können wir diesen Kollektor jedoch einen benutzerdefinierten Typ zurückgeben lassen:
public static > Collector> toImmutableList(
Supplier supplier) {
return Collector.of(
supplier,
List::add, (left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableList);
}
Anstatt nun diesupplier in der Methodenimplementierung zu bestimmen, fordern wir diesupplier vom Benutzer an:
@Test
public void whenPassingSupplier_thenSuccess() {
List givenList = Arrays.asList("a", "b", "c", "d");
List result = givenList.stream()
.collect(MyImmutableListCollector.toImmutableList(LinkedList::new));
}
Bitte beachten Sie, dass wir jetztLinkedList anstelle vonArrayList verwenden. Lassen Sie uns dies ausführen und die Ergebnisse sehen:
class java.util.Collections$UnmodifiableList
Dieses Mal haben wirUnmodifiableList anstelle vonUnmodifiableRandomAccessList.
6. Fazit
In diesem kurzen Artikel haben wir verschiedene Möglichkeiten gesehen, einStream in ein unveränderlichesCollection zu sammeln.
Stellen Sie sicher, dass Sie den vollständigen Quellcode dieses Artikelsover on GitHub lesen.