Recueillir un flux Java dans une collection immuable
1. introduction
Dans cet article rapide, nous allons examiner différentes manières de collecter desStreams Java vers desCollections – immuables qui nécessitent une approche spéciale car lesCollectorstandard ne fonctionnent qu'avec des structures de données mutables.
2. Dépendance Maven
Nous allons utiliser la bibliothèque Guava de Google pour piloter certains de nos exemples:
com.google.guava
guava
22.0
Nous pouvons obtenir la dernière version de cette dépendance à partir dehere.
3. Utilisation descollectingAndThen() de Java
La méthodecollectingAndThen() de la classeCollectors de Java accepte unCollector et unfinisherFunction qui est appliqué au résultat renvoyé par lesCollector:
@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());
}
Puisque nous ne pouvons pas utiliser la toCollection() Collector directement,, nous devons collecter des éléments dans une liste temporaire, puis en construire une liste immuable.
Dans cet exemple, nous convertissons unStream en unList à l'aide du collecteurtoList(), puis créons unImmutableList. LeImmutableList fait partie de la bibliothèque Guava. Si nous enregistrons la sortie dans la console, nous obtiendrons la classe du sous-jacent
Si nous enregistrons la sortie dans la console, nous obtiendrons la classe de l'implémentation sous-jacente deList:
class com.google.common.collect.RegularImmutableList
4. Utilisation desCollectors de Guava
À partir de Guava 21, chaque classe immuable s'accompagne d'unCollector qui est aussi facile à utiliser que lesCollectors: standard
@Test
public void whenCollectToImmutableList_thenSuccess() {
List list = IntStream.range(0, 9)
.boxed()
.collect(ImmutableList.toImmutableList());
}
L'instance résultante est leRegularImmutableList:
class com.google.common.collect.RegularImmutableList
5. Créer un collecteur personnalisé
Maintenant, allons plus loin et implémentons nosCollector personnalisés. Pour atteindre cet objectif, nous allons utiliser la méthode statiqueCollector.of():
public static Collector, List> toImmutableList() {
return Collector.of(ArrayList::new, List::add,
(left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableList);
}
Pour en savoir plus sur l'implémentation deCollectors personnalisés, veuillez consulter la section 4 dethis article. Et c'est tout. La méthode ci-dessus fait partie de notre classe personnalisée
Nous pouvons l'utiliser maintenant comme n'importe quel autreCollectors intégré:
@Test
public void whenCollectToMyImmutableListCollector_thenSuccess() {
List givenList = Arrays.asList("a", "b", "c", "d");
List result = givenList.stream()
.collect(MyImmutableListCollector.toImmutableList());
}
Enfin, vérifions le résultat:
class java.util.Collections$UnmodifiableRandomAccessList
5.1. Rendre leMyImmutableListCollector générique
Notre implémentation a une limitation - elle renvoie toujours une instance immuable soutenue par unArrayList. Cependant, avec une légère amélioration, nous pouvons faire en sorte que ce collecteur retourne un type spécifié par l'utilisateur:
public static > Collector> toImmutableList(
Supplier supplier) {
return Collector.of(
supplier,
List::add, (left, right) -> {
left.addAll(right);
return left;
}, Collections::unmodifiableList);
}
Maintenant, au lieu de déterminer lessupplier dans l'implémentation de la méthode, nous demandons lessupplier à l'utilisateur:
@Test
public void whenPassingSupplier_thenSuccess() {
List givenList = Arrays.asList("a", "b", "c", "d");
List result = givenList.stream()
.collect(MyImmutableListCollector.toImmutableList(LinkedList::new));
}
Veuillez noter que nous utilisons maintenant lesLinkedList au lieu deArrayList. Exécutons ceci et voyons les résultats:
class java.util.Collections$UnmodifiableList
Cette fois, nous avons obtenuUnmodifiableList au lieu deUnmodifiableRandomAccessList.
6. Conclusion
Dans ce court article, nous avons vu différentes manières de collecter unStream dans unCollection immuable.
Assurez-vous de consulter le code source complet de cet articleover on GitHub.