流式传输迭代器的最简单方法

2022-09-03 15:19:07

假设你想流式传输迭代器的元素;让我们使用一个具体的例子,它实现 。ScannerIterator<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 的某个地方是否有返回给定的工厂方法?Stream<T>Iterator<T>


答案 1

我会简单地使用.是的,它是一个无限的流,但是扫描仪也是如此,除非您知道您要求多少行,在这种情况下,它很容易使用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

return new BufferedReader(new InputStreamReader(System.in)).lines();

答案 2