流式传输迭代器的最简单方法
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<String>
的选项很笨重:
StreamSupport.stream(
Spliterators.spliteratorUnknownSize(scanner, Spliterator.ORDERED), false);
或者更简洁,但钝:
StreamSupport.stream(
((Iterable<String>) () -> new Scanner(System.in)).spliterator(), false);
在给定Iterator<T>
的情况下,JDK 中是否有返回Stream<T>
的工厂方法?
【问题讨论】:
你说new Scanner(System.in); // it's an Iterable<String>
让我很困惑
没有更简单的方法,但这真的那么普遍,需要更简单的方法吗?
@holger 因为class Scanner implements Iterator<String>
是的,我经常想流式传输迭代器的元素(当然不仅仅是扫描仪,这只是不是集合的 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<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();
【讨论】:
以上是关于流式传输迭代器的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章
在不使用定价服务作为推送器的情况下创建 Laravel 广播的最简单方法是啥?