web-dev-qa-db-fra.com

Regrouper le flux Java8 sans le collecter

Existe-t-il un moyen dans Java 8 pour regrouper les éléments dans un Java.util.stream.Stream sans les récupérer? Je veux que le résultat soit à nouveau un Stream. Parce que je dois travailler avec beaucoup de données ou même des flux infinis, je ne peux pas collecter les données en premier et diffuser à nouveau le résultat.

Tous les éléments qui doivent être groupés sont consécutifs dans le premier flux. Par conséquent, j'aime garder l'évaluation du flux paresseuse.

32
Matthias Wimmer

Il n'y a aucun moyen de le faire en utilisant l'API Stream standard. En général, vous ne pouvez pas le faire car il est toujours possible qu'un nouvel élément apparaisse à l'avenir qui appartient à l'un des groupes déjà créés, vous ne pouvez donc pas passer votre groupe à l'analyse en aval tant que vous n'avez pas traité toutes les entrées.

Cependant, si vous savez à l'avance que les éléments à regrouper sont toujours adjacents dans le flux d'entrée, vous pouvez résoudre votre problème en utilisant des bibliothèques tierces améliorant l'API Stream. L'une de ces bibliothèques est StreamEx qui est gratuite et écrite par moi. Il contient un certain nombre d'opérateurs de "réduction partielle" qui réduisent les éléments adjacents en un seul en fonction d'un prédicat. Habituellement, vous devez fournir un BiPredicate qui teste deux éléments adjacents et renvoie true s'ils doivent être regroupés. Certaines opérations de réduction partielle sont répertoriées ci-dessous:

  • collapse(BiPredicate) : remplacez chaque groupe par le premier élément du groupe. Par exemple, collapse(Objects::equals) est utile pour supprimer les doublons adjacents du flux.
  • groupRuns(BiPredicate) : remplacez chaque groupe par la liste des éléments du groupe (donc StreamEx<T> est converti en StreamEx<List<T>>). Par exemple, stringStream.groupRuns((a, b) -> a.charAt(0) == b.charAt(0)) créera un flux de listes de chaînes où chaque liste contient des chaînes adjacentes commençant par la même lettre.

D'autres opérations de réduction partielle incluent intervalMap , runLengths() et ainsi de suite.

Toutes les opérations de réduction partielle sont paresseuses, conviviales en parallèle et assez efficaces.

Notez que vous pouvez facilement construire un objet StreamEx à partir d'un flux régulier Java 8 en utilisant StreamEx.of(stream). Il existe également des méthodes pour le construire à partir de array, Collection, Reader , etc. La classe StreamEx implémente l'interface Stream et 100% compatible avec l'API Stream standard.

28
Tagir Valeev