假设你想要流化迭代器的元素;让我们使用Scanner
的具体示例,它实现了Iterator<String>
。
给定一个Iterator
,说:
// Scanner implements Iterator<String>
Iterator<String> scanner = new Scanner(System.in);
从它创建Stream<String>
的选项很笨拙:
StreamSupport.stream(
Spliterators.spliteratorUnknownSize(scanner, Spliterator.ORDERED), false);
或者更简洁但更钝的:
StreamSupport.stream(
((Iterable<String>) () -> new Scanner(System.in)).spliterator(), false);
在JDK中是否有一个工厂方法返回给定Iterator<T>
的Stream<T>
?
我只使用Stream.generate(iterator::next)
。是的,它是一个无限流,但System.in
的扫描器也是,除非你知道你要请求多少行,在这种情况下,使用
Stream.generate(iterator::next).limit(numLines);
这样可以避免迭代器必须迭代两次(一次作为迭代器,一次作为流)。
如果你需要一个大小的流,而不知道它有多大,但不想让你的代码混乱,只需创建一个实用程序方法,显式地接受Iterable<T>
:
public static <T> Stream<T> stream(Iterable<T> it){
return StreamSupport.stream(it.spliterator(), false);
}
它最终比试图将所有内容塞进一行更容易读懂,并且然后你可以调用stream(()->iterator);
或stream(()->new Scanner(System.in));
您也可以很容易地添加第二个方便方法:
public static <T> Stream<T> stream(Iterator<T> it){
return stream(()->it);
}
允许您调用stream(iterator);
或stream(new Scanner(System.in));
虽然,如果我要将System.in
读取到流中,我可能会使用Reader而不是Scanner:
return new BufferedReader(new InputStreamReader(System.in)).lines();