recorrer que obtener linkedlist español elemento ejemplo java iterator java-8

que - recorrer arraylist java foreach



¿Cómo convertir un iterador a un flujo? (6)

Estoy buscando una forma concisa de convertir un Iterator en un Stream o más específicamente para "ver" el iterador como un flujo.

Por motivos de rendimiento, me gustaría evitar una copia del iterador en una nueva lista:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Collection<String> copyList = new ArrayList<String>(); sourceIterator.forEachRemaining(copyList::add); Stream<String> targetStream = copyList.stream();

Basándome en algunas sugerencias de los comentarios, también he intentado usar Stream.generate :

public static void main(String[] args) throws Exception { Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Stream<String> targetStream = Stream.generate(sourceIterator::next); targetStream.forEach(System.out::println); }

Sin embargo, obtengo una NoSuchElementException (ya que no hay invocación de hasNext )

Exception in thread "main" java.util.NoSuchElementException at java.util.AbstractList$Itr.next(AbstractList.java:364) at Main$$Lambda$1/1175962212.get(Unknown Source) at java.util.stream.StreamSpliterators$InfiniteSupplyingSpliterator$OfRef.tryAdvance(StreamSpliterators.java:1351) at java.util.Spliterator.forEachRemaining(Spliterator.java:326) at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580) at Main.main(Main.java:20)

He visto StreamSupport y Collections pero no he encontrado nada.


Crear Spliterator desde Spliterator usando la clase Spliterators contiene más de una función para crear Spliterator, por ejemplo, aquí estoy usando spliteratorUnknownSize que está obteniendo iterador como parámetro, luego cree Stream usando StreamSupport

Spliterator<Model> spliterator = Spliterators.spliteratorUnknownSize( iterator, Spliterator.NONNULL); Stream<Model> stream = StreamSupport.stream(spliterator, false);


Desde la versión 21, la biblioteca de Guava proporciona Streams.stream(iterator)

Hace lo que muestra la respuesta de @ assylias .


Esto es posible en Java 9 usando nada más que flujos, sin embargo, hay una advertencia a tener en cuenta. El siguiente ejemplo ingenuo no podrá imprimir el último elemento del iterador.

Stream.generate(iterator::next) .takeWhile(i -> iterator.hasNext()) .forEach(System.out::println);

Esto, sin embargo, funciona correctamente:

Stream.generate(() -> null) .takeWhile(x -> iterator.hasNext()) .map(n -> iterator.next()) .forEach(System.out::println);


Gran sugerencia! Aquí está mi versión reutilizable:

public class StreamUtils { public static <T> Stream<T> asStream(Iterator<T> sourceIterator) { return asStream(sourceIterator, false); } public static <T> Stream<T> asStream(Iterator<T> sourceIterator, boolean parallel) { Iterable<T> iterable = () -> sourceIterator; return StreamSupport.stream(iterable.spliterator(), parallel); } }

Y el uso (asegúrese de importar estáticamente como asStream):

List<String> aPrefixedStrings = asStream(sourceIterator) .filter(t -> t.startsWith("A")) .collect(toList());


Una forma es crear un separador desde el iterador y usarlo como base para su transmisión:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Stream<String> targetStream = StreamSupport.stream( Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED), false);

Una alternativa que quizás sea más legible es usar un Iterable, y crear un Iterable desde un Iterator es muy fácil con las lambdas porque Iterable es una interfaz funcional:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator(); Iterable<String> iterable = () -> sourceIterator; Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);


Utilice Collections.list(iterator).stream()...