En Java 8 tenemos la clase Stream <T> , que curiosamente tiene un método
Iterator<T> iterator()
Por lo tanto, es de esperar que implemente la interfaz Iterable <T> , que requiere exactamente este método, pero ese no es el caso.
Cuando quiero iterar sobre un Stream usando un bucle foreach, tengo que hacer algo como
public static Iterable<T> getIterable(Stream<T> s) {
return new Iterable<T> {
@Override
public Iterator<T> iterator() {
return s.iterator();
}
};
}
for (T element : getIterable(s)) { ... }
¿Me estoy perdiendo de algo?
java
java-8
java-stream
iterable
roim
fuente
fuente
Stream
a las API heredadas que esperaIterable
getIterable()
quereturn s::iterator;
for (T element : stream::iterator)
, por lo que aún preferiría que Stream también implementaraIterable
o un métodotoIterable()
.Respuestas:
La gente ya ha preguntado lo mismo en la lista de correo ☺. La razón principal es que Iterable también tiene una semántica repetible, mientras que Stream no lo es.
fuente
Iterable
sobre siiterator
debería o no ser invocable varias veces. Eso es algo que deberían poner allí. Esto parece ser más una práctica estándar que una especificación formal.Para convertir un
Stream
a unIterable
, puedes hacerPara pasar
Stream
a un método que esperaIterable
,simplemente
sin embargo, probablemente se ve divertido; podría ser mejor ser un poco más explícito
fuente
for(X x : (Iterable<X>)stream::iterator)
, aunque se ve feo. Realmente, toda la situación es simplemente absurda.IntStream.range(0,N).forEach(System.out::println)
stream::iterator
ystream.iterator()
, eso hace que el primero sea aceptable para unIterable
pero no el segundo?Iterable
es una interfaz funcional, por lo que pasar una función que la implemente es suficiente.Me gustaría señalar que
StreamEx
implementaIterable
(yStream
), así como una gran cantidad de otras funcionalidades inmensamente increíbles que faltanStream
.fuente
Puede usar una secuencia en un
for
bucle de la siguiente manera:(Ejecute este fragmento aquí )
(Esto utiliza una conversión de interfaz funcional Java 8).
(Esto está cubierto en algunos de los comentarios anteriores (por ejemplo, Aleksandr Dubinsky ), pero quería sacarlo en una respuesta para hacerlo más visible).
fuente
kennytm describió por qué no es seguro tratar un
Stream
como unIterable
, y Zhong Yu ofreció una solución alternativa que permite usar unStream
como enIterable
, aunque de manera insegura. Es posible obtener lo mejor de ambos mundos: un reutilizableIterable
de unoStream
que cumpla con todas las garantías hechas por laIterable
especificación.Nota:
SomeType
no es un parámetro de tipo aquí; debe reemplazarlo con un tipo adecuado (por ejemplo,String
) o recurrir a la reflexiónHay una gran desventaja:
Los beneficios de la iteración perezosa se perderán. Si planeaba iterar inmediatamente sobre todos los valores en el hilo actual, cualquier sobrecarga será insignificante. Sin embargo, si planeaba iterar solo parcialmente o en un hilo diferente, esta iteración inmediata y completa podría tener consecuencias no deseadas.
La gran ventaja, por supuesto, es que puede reutilizar
Iterable
, mientras(Iterable<SomeType>) stream::iterator
que solo permitiría un solo uso. Si el código de recepción iterará en la colección varias veces, esto no solo es necesario, sino que probablemente sea beneficioso para el rendimiento.fuente
Stream.toArray()
devuelve una matriz, no unIterable
, por lo que este código aún no se compila. pero puede ser un error en eclipse, ya que IntelliJ parece compilarloStream
no implementaIterable
. La comprensión general deIterable
es todo lo que se puede repetir, a menudo una y otra vez.Stream
puede no ser rejugableLa única solución que se me ocurre, en la que también se puede reproducir un iterable basado en una secuencia, es volver a crear la secuencia. Estoy usando un
Supplier
siguiente para crear una nueva instancia de transmisión, cada vez que se crea un nuevo iterador.fuente
Si no le importa usar bibliotecas de terceros, cyclops-react define un Stream que implementa Stream e Iterable y que también se puede volver a reproducir (resolviendo el problema descrito por kennytm ).
o: -
[Divulgación Soy el desarrollador principal de cyclops-react]
fuente
No es perfecto, pero funcionará:
No es perfecto, ya que se ha podido recuperar todos los elementos de la corriente y ponerlos en que
List
, lo que no es exactamente lo queIterable
yStream
están a punto. Se supone que son flojos .fuente
Puede iterar sobre todos los archivos en una carpeta usando
Stream<Path>
así:fuente