Szukam zwięzłego sposobu przekonwertowania pliku Iterator
na Stream
lub bardziej szczegółowo, aby „wyświetlić” iterator jako strumień.
Ze względu na wydajność chciałbym uniknąć kopiowania iteratora na nowej liście:
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Collection<String> copyList = new ArrayList<String>();
sourceIterator.forEachRemaining(copyList::add);
Stream<String> targetStream = copyList.stream();
W oparciu o niektóre sugestie w komentarzach próbowałem również użyć 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);
}
Dostaję jednak NoSuchElementException
(ponieważ nie ma wywołania 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)
Patrzyłem StreamSupport
i Collections
nic nie znalazłem.
Stream.generate(iterator::next)
działa?Odpowiedzi:
Jednym ze sposobów jest utworzenie Spliteratora z Iteratora i użycie go jako podstawy dla twojego strumienia:
Alternatywą, która może być bardziej czytelna, jest użycie Iterable - a tworzenie Iterable z Iteratora jest bardzo proste w lambdach, ponieważ Iterable to funkcjonalny interfejs:
źródło
sourceIterator.next()
przed użyciem strumienia, a zobaczysz efekt (pierwszy element nie będzie widoczny w strumieniu).Iterable<String> iterable = () -> sourceIterator;
. Muszę przyznać, że zrozumienie zajęło mi trochę czasu.Iterable<T>
toFunctionalInterface
metoda, która ma tylko jedną metodę abstrakcyjnąiterator()
. Podobnie() -> sourceIterator
jak wyrażenie lambda, które tworzyIterable
instancję jako anonimową implementację.() -> sourceIterator;
jest skróconą formąnew Iterable<>() { @Override public Iterator<String> iterator() { return sourceIterator; } }
Od wersji 21 biblioteka Guava zapewnia
Streams.stream(iterator)
To co robi @ assylias „s odpowiedź pokazy .
źródło
Świetna sugestia! Oto moje zdanie na ten temat:
I użycie (pamiętaj, aby zaimportować statycznie asStream):
źródło
Jest to możliwe w Javie 9.
źródło
.parallel()
strumieniami. Wydają się również nieco wolniejsze niż przejścieSpliterator
, nawet w przypadku użycia sekwencyjnego.parallel
może być funky, prostota jest niesamowita.Klasa Create
Spliterator
fromIterator
usingSpliterators
zawiera więcej niż jedną funkcję do tworzenia spliteratora, na przykład tutaj używam,spliteratorUnknownSize
który pobiera iterator jako parametr, a następnie tworzę Stream za pomocąStreamSupport
źródło
i użyj
Streams.stream(iterator)
:źródło
Posługiwać się
Collections.list(iterator).stream()...
źródło