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

Posted

技术标签:

【中文标题】流式传输迭代器的最简单方法【英文标题】:Simplest way to stream an iterator 【发布时间】:2015-11-25 20:47:44 【问题描述】:

假设您要流式传输迭代器的元素;让我们使用一个Scanner 的具体示例,它实现了Iterator<String>

给定一个Iterator,说:

// Scanner implements Iterator<String>
Iterator<String> scanner = new Scanner(System.in);

从中创建Stream&lt;String&gt; 的选项很笨重:

StreamSupport.stream(
  Spliterators.spliteratorUnknownSize(scanner, Spliterator.ORDERED), false);

或者更简洁,但钝:

 StreamSupport.stream(
  ((Iterable<String>) () -> new Scanner(System.in)).spliterator(), false);

在给定Iterator&lt;T&gt; 的情况下,JDK 中是否有返回Stream&lt;T&gt; 的工厂方法?

【问题讨论】:

你说new Scanner(System.in); // it's an Iterable&lt;String&gt;让我很困惑 没有更简单的方法,但这真的那么普遍,需要更简单的方法吗? @holger 因为class Scanner implements Iterator&lt;String&gt; 是的,我经常想流式传输迭代器的元素(当然不仅仅是扫描仪,这只是不是集合的 Itrator 的示例)跨度> 对于它的价值,关于扫描仪,https://bugs.openjdk.java.net/browse/JDK-8072722。 Java8 Iterator to Stream的可能重复 【参考方案1】:

我会简单地使用Stream.generate(iterator::next)。是的,它是一个无限流,但来自System.in 的扫描仪也是如此,除非你知道你需要多少行,在这种情况下它很容易使用

Stream.generate(iterator::next).limit(numLines);

这可以防止迭代器被迭代两次(一次作为迭代器,一次作为流)。

如果您需要一个大小合适的流但不知道它有多大,但又不想弄乱您的代码,只需创建一个显式采用 Iterable&lt;T&gt; 的实用程序方法:

public static <T> Stream<T> stream(Iterable<T> it)
    return StreamSupport.stream(it.spliterator(), false);
  

它最终比试图将所有内容都塞在一条线上更清晰,并且 那么你可以打电话给stream(()-&gt;iterator);stream(()-&gt;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();

【讨论】:

以上是关于流式传输迭代器的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章

在不使用定价服务作为推送器的情况下创建 Laravel 广播的最简单方法是啥?

是否可以保存通过 RTMP 流式传输的 flv 视频?

Python:迭代器的简单理解

通过 Javascript 迭代复杂 JSON 对象的最简单方法

在 2 个 C 程序之间传输数据的最简单方法是啥?

在枚举python中包含停止参数的最简单方法?