Stream
hereda un método iterator () para producir un Iterator
.
Pero necesito una en Iterable
lugar de una Iterator
.
Por ejemplo, dada esta cadena:
String input = "this\n" +
"that\n" +
"the_other";
... Necesito pasar esas partes de cadena como una Iterable
a una biblioteca específica. Llamar input.lines()
rinde a Stream
. Así que estaría listo si pudiera convertir eso Stream
en uno Iterable
de sus elementos.
java
java-stream
iterable
Albahaca Bourque
fuente
fuente
Respuestas:
Como se explica en ¿Por qué Stream <T> no implementa Iterable <T>? ,
Iterable
tiene la expectativa de poder proporcionarIterator
más de una vez, lo queStream
no puede cumplir. Entonces, si bien puede crear unIterable
fuera de aStream
para un uso ad-hoc, debe tener cuidado con la posibilidad de que existan intentos de iterarlo varias veces.Como usted dijo: " Necesito pasar esas partes de la cadena como una
Iterable
a una biblioteca específica ", no hay una solución general ya que el código que usaIterable
está fuera de su control.Pero si usted es quien crea la secuencia, es posible crear una válida
Iterable
que simplemente repita la construcción de la secuencia cada vez queIterator
se solicita:Esto cumple la expectativa de soportar un número arbitrario de iteraciones, sin consumir más recursos que una sola secuencia cuando se atraviesa solo una vez.
fuente
Iterable<String> lines = "this\nthat\nthe_other".lines()::iterator;
este es uno de esos casos raros en los que una referencia de método no es lo mismo que una lambda y, de hecho, tendría un efecto no deseado.expression::name
nunca son las mismas que las expresiones lambda, ni siquiera paraSystem.out::println
. Pero aquí, tenemos uno de los casos donde importaStream<String> lines = str.lines();
creas elIterable<String> iter = lines::iterator
versus()->lines.iterator()
.stream::iterator
y() -> stream.iterator()
. De hecho, mi respuesta dijo con precisión que no existe una solución general para convertir una secuencia existente en una iteración válida que permita múltiples iteraciones. Repetir la construcción de la secuencia cada vez que se solicita un iterador, es decir, aquí significa llamarlines()
cada vez, es lo que marca la diferencia.expression::name
significa " evaluarexpression
una vez y capturar el resultado ", mientras que() -> expression.name(…)
significa " evaluarexpression
cada vez que se evalúa el cuerpo de la función ". Las diferencias son pequeñas cuando "expression
" es solo una variable local, pero aun así, es diferente, es decir,stream::iterator
se comportará de manera diferente a() -> stream.iterator()
cuandostream
esnull
. Por lo tanto, mi afirmación aún se mantiene,expression::name
siempre es diferente a una expresión lambda, la pregunta es, ¿cuánto importa para mi caso de uso específico?tl; dr
Recién lanzado , no hay necesidad de convertir.
Cast
Stream < String >
aIterable < String >
.Detalles
PRECAUCIÓN Consulte la Respuesta de Holger que explica los peligros del uso de un flujo respaldado
Iterable
.Sí, puedes hacer un
Iterable
de aStream
.La solución es simple, pero no obvia. Vea esta publicación en las Preguntas frecuentes sobre Lambda de Maurice Naftalin .
El
iterator()
método enBaseStream
(superclase deStream
) que devuelve unIterator
coincide con el mismo nombre deliterator()
método que devuelve unIterator
como lo requiere laIterable
interfaz. Las firmas del método coinciden. Por lo tanto, podemos convertirlo enStream
aIterable
, no se necesita conversión.Haz tu aportación.
Echa eso
Stream<String>
aIterable<String>
.Prueba los resultados.
Vea este código en vivo en IdeOne.com .
CUIDADO Tenga cuidado con el riesgo de la transmisión de respaldo
Iterable
. Explicado en la respuesta correcta de Holger .fuente
Stream<String>
porquestream::iterator
no es de tipoStream<String>
.Iterable
través de una referencia de método; el(Iterable<String>)
simplemente le dice al compilador qué interfaz funcional es el objetivo.(Iterable<String>)
es nada más que un elenco, sin embargo, ciertamente no entiendo la situación, ya que sus comentarios me impulsaron a colocar un conjunto adicional de parens( (Iterable<String>) stream )
que causa que el código falle, lo que demuestra que mi comprensión es defectuosa. Así que edite mi respuesta para aclarar o publique su propia respuesta con una mejor explicación.(Iterable<String>)()->stream.iterator()
o incluso más explícitamentenew Iterable<String>(){ public Iterator<String> iterator(){ return stream.iterator();}
. Por lo tanto, no está emitiendo un Stream a Iterable, lo que podría fallar.