Convertissez Iterable en Stream en utilisant Java 8 JDK

J’ai une interface qui renvoie java.lang.Iterable .

Je voudrais manipuler ce résultat en utilisant l’API Java 8 Stream.

Cependant, on ne peut pas “Stream”.

Une meilleure idée de l’utilisation des stream (sans convertir Iterable en liste)?

Il y a une réponse bien meilleure que l’utilisation de spliteratorUnknownSize directement, ce qui est à la fois plus facile et donne un meilleur résultat. Iterable a une méthode spliterator() , vous devez donc l’utiliser pour obtenir votre spliterator. Dans le pire des cas, c’est le même code (l’implémentation par défaut utilise spliteratorUnknownSize ), mais dans le cas le plus courant, où votre Iterable est déjà une collection, vous obtiendrez un meilleur spliterator et donc une meilleure performance .) Son aussi moins de code:

 StreamSupport.stream(iterable.spliterator(), false) .filter(...) .moreStreamOps(...); 

Comme vous pouvez le voir, obtenir un stream depuis une Iterable (voir Pourquoi Iterable ne fournit-il pas les méthodes stream () et parallelStream ()? ) N’est pas très douloureux.

Si vous pouvez utiliser la bibliothèque Guava, depuis la version 21, vous pouvez utiliser

 Streams.stream(iterable) 

Vous pouvez facilement créer un Stream partir d’un Iterable ou d’un Iterator :

 public static  Stream stream(Iterable iterable) { return StreamSupport.stream( Spliterators.spliteratorUnknownSize( iterable.iterator(), Spliterator.ORDERED ), false ); } 

Je voudrais suggérer d’utiliser la bibliothèque JOOL , elle cache la magie du spliterator derrière l’appel Seq.seq (itérable) et fournit également toute une série de fonctionnalités supplémentaires utiles.

J’ai créé cette classe:

 public class Streams { /** * Converts Iterable to stream */ public static  Stream streamOf(final Iterable iterable) { return toStream(iterable, false); } /** * Converts Iterable to parallel stream */ public static  Stream parallelStreamOf(final Iterable iterable) { return toStream(iterable, true); } private static  Stream toStream(final Iterable iterable, final boolean isParallel) { return StreamSupport.stream(iterable.spliterator(), isParallel); } } 

Je pense que c’est parfaitement lisible parce que vous n’avez pas à penser aux spliterators et aux booléens (isParallel).

Un moyen très simple de contourner ce problème consiste à créer une Streamable étendue à Iterable qui contient une méthode default stream() .

 interface Streamable extends Iterable { default Stream stream() { return StreamSupport.stream(spliterator(), false); } } 

Maintenant, n’importe lequel de vos Iterable peut être rendu sortingvialement en streaming simplement en les déclarant implements Streamable au lieu de Iterable .

Donc, comme une autre réponse mentionnée Guava a le soutien en utilisant:

 Streams.stream(iterable); 

Je tiens à souligner que la mise en œuvre fait quelque chose de légèrement différent des autres réponses suggérées. Si l’ Iterable est de type Collection il est lancé.

 public static  Stream stream(Iterable iterable) { return (iterable instanceof Collection) ? ((Collection) iterable).stream() : StreamSupport.stream(iterable.spliterator(), false); } public static  Stream stream(Iterator iterator) { return StreamSupport.stream( Spliterators.spliteratorUnknownSize(iterator, 0), false ); } 

Si vous utilisez Vavr (anciennement Javaslang), cela peut être aussi simple que:

 Iterable i = //... Stream.ofAll(i);