私は Iterator
を Stream
に変換する簡潔な方法、またはより具体的にはイテレータをストリームとして "見る"方法を探しています。
パフォーマンス上の理由から、新しいリストではイテレータのコピーを避けたいと思います。
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Collection<String> copyList = new ArrayList<String>();
sourceIterator.forEachRemaining(copyList::add);
Stream<String> targetStream = copyList.stream();
コメント内のいくつかの提案に基づいて、私は 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);
}
しかし、私はNoSuchElementException
を受け取ります(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)
StreamSupport
と Collections
を見ましたが、何も見つかりませんでした。
1つの方法は、IteratorからSpliteratorを作成し、それをストリームの基盤として使用することです。
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Stream<String> targetStream = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(sourceIterator, Spliterator.ORDERED),
false);
もっと読みやすい代替方法はIterableを使用することです - Iterableは機能的なインタフェースなので、IteratorからIterableを作成するのはとても簡単です。
Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
Iterable<String> iterable = () -> sourceIterator;
Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);
バージョン21以降、Guavaライブラリは Streams.stream(iterator)
を提供しています。
@ assylias answerが示すことを行います。
大提案!これが私の再利用可能な話です。
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);
}
}
そして使用法(静的にasStreamをインポートするようにしてください):
List<String> aPrefixedStrings = asStream(sourceIterator)
.filter(t -> t.startsWith("A"))
.collect(toList());
これはJava 9ではストリーム以外は何も使用しないで可能ですが、注意が必要です。次の単純な例では、 イテレータの最後の要素 を表示できません。
Stream.generate(iterator::next)
.takeWhile(i -> iterator.hasNext())
.forEach(System.out::println);
ただし、これは正しく機能します。
Stream.generate(() -> null)
.takeWhile(x -> iterator.hasNext())
.map(n -> iterator.next())
.forEach(System.out::println);
Spliterator
name__クラスを使用してIterator
name__からSpliterators
name__を作成します。例えば、ここではイテレーターをパラメーターとして取得しているspliteratorUnknownSize
name__を使用しています。そしてStreamSupport
name__を使用してStreamを作成します。
Spliterator<Model> spliterator = Spliterators.spliteratorUnknownSize(
iterator, Spliterator.NONNULL);
Stream<Model> stream = StreamSupport.stream(spliterator, false);