Java 如何将迭代器转换为流?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24511052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 12:41:04  来源:igfitidea点击:

How to convert an iterator to a stream?

javaiteratorjava-8

提问by gontard

I am looking for a concise way to convert an Iteratorto a Streamor more specifically to "view" the iterator as a stream.

我正在寻找一种简洁的方法将 an 转换Iterator为 aStream或更具体地将迭代器“查看”为流。

For performance reason, I would like to avoid a copy of the iterator in a new list:

出于性能原因,我想避免在新列表中复制迭代器:

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


Based on the some suggestions in the comments, I have also tried to use Stream.generate:

根据评论中的一些建议,我也尝试使用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);
}

However, I get a NoSuchElementException(since there is no invocation of hasNext)

但是,我得到了一个NoSuchElementException(因为没有调用hasNext

Exception in thread "main" java.util.NoSuchElementException
    at java.util.AbstractList$Itr.next(AbstractList.java:364)
    at Main$$Lambda/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)

I have looked at StreamSupportand Collectionsbut I didn't find anything.

我已经看过了StreamSupportCollections但我什么也没找到。

采纳答案by assylias

One way is to create a Spliterator from the Iterator and use that as a basis for your stream:

一种方法是从 Iterator 创建一个 Spliterator 并将其用作流的基础:

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

An alternative which is maybe more readable is to use an Iterable - and creating an Iterable from an Iterator is very easy with lambdas because Iterable is a functional interface:

另一种可能更具可读性的替代方法是使用 Iterable - 使用 lambdas 从 Iterator 创建 Iterable 非常容易,因为 Iterable 是一个功能接口:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();

Iterable<String> iterable = () -> sourceIterator;
Stream<String> targetStream = StreamSupport.stream(iterable.spliterator(), false);

回答by Matan

Great suggestion! Here's my reusable take on it:

很棒的建议!这是我对它的可重复使用的看法:

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);
    }
}

And usage (make sure to statically import asStream):

和用法(确保静态导入 asStream):

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

回答by Bassem Reda Zohdy

Create Spliteratorfrom Iteratorusing Spliteratorsclass contains more than one function for creating spliterator, for example here am using spliteratorUnknownSizewhich is getting iterator as parameter, then create Stream using StreamSupport

Create Spliteratorfrom Iteratorusing Spliteratorsclass 包含多个用于创建 spliterator 的函数,例如这里使用的spliteratorUnknownSize是获取迭代器作为参数,然后使用创建流StreamSupport

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

回答by numéro6

Since version 21, Guava library provides Streams.stream(iterator)

从版本 21 开始,Guava 库提供 Streams.stream(iterator)

It does what @assylias's answer shows.

它执行@assylias回答所显示的内容

回答by Israel C. S. Rocha

Use Collections.list(iterator).stream()...

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

回答by PhilipRoman

This is possible in Java 9.

这在 Java 9 中是可能的。

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

回答by sneha

import com.google.common.collect.Streams;

and use Streams.stream(iterator):

并使用Streams.stream(iterator)

Streams.stream(iterator)
       .map(v-> function(v))
       .collect(Collectors.toList());