Convierta Iterable a Stream utilizando Java 8 JDK

Tengo una interfaz que devuelve java.lang.Iterable .

Me gustaría manipular ese resultado utilizando Java 8 Stream API.

Sin embargo, Iterable no puede “transmitir”.

¿Alguna idea mejor de cómo usar las transmisiones (sin convertir Iterable a List)?

Hay una respuesta mucho mejor que usar spliteratorUnknownSize directamente, que es más fácil y obtiene un mejor resultado. Iterable tiene un método spliterator() , por lo que debe usarlo para obtener su spliterator. En el peor de los casos, es el mismo código (la implementación predeterminada usa spliteratorUnknownSize ), pero en el caso más común, donde tu Iterable ya es una colección, obtendrás un spliterator mejor y, por lo tanto, mejor rendimiento de transmisión (incluso un buen paralelismo) .) También es menos código:

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

Como puede ver, obtener un flujo de un Iterable (consulte ¿Por qué Iterable no proporciona los métodos stream () y parallelStream ()? ) No es muy doloroso.

Si puede usar la biblioteca de guayaba, desde la versión 21, puede usar

 Streams.stream(iterable) 

Puede crear fácilmente un Stream de un Iterable o Iterator :

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

Me gustaría sugerir el uso de la biblioteca JOOL , oculta la magia del spliterator detrás de la llamada Seq.seq (iterable) y también proporciona un montón de funcionalidades útiles adicionales.

Creé esta clase:

 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); } } 

Creo que es perfectamente legible porque no tienes que pensar en spliterators y booleans (isParallel).

Una Streamable muy simple para este problema es crear una Streamable Iterable que contenga un método default stream() .

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

Ahora cualquiera de tus Iterable s puede hacerse trivialmente streamable simplemente al declarar que implements Streamable lugar de Iterable .

Entonces, como otra respuesta mencionada, Guava tiene soporte para esto al usar:

 Streams.stream(iterable); 

Quiero resaltar que la implementación hace algo ligeramente diferente de otras respuestas sugeridas. Si el Iterable es de tipo Collection lo lanzan.

 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 usa Vavr (anteriormente conocido como Javaslang), esto puede ser tan fácil como:

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