将流变成可迭代? [重复]

问题描述 投票:0回答:2

Stream
继承了 iterator() 方法来生成
Iterator

但我需要一个

Iterable
而不是
Iterator

例如,给定这个字符串:

String input = "this\n" +
        "that\n" +
        "the_other";

…我需要将字符串的这些部分作为

Iterable
传递到特定的库。调用
input.lines()
会产生
Stream
。因此,如果我可以将
Stream
变成其元素的
Iterable
,我就确定了。

java java-stream iterable
2个回答
49
投票

正如为什么 Stream 不实现 Iterable 中所解释的,

Iterable
承载着能够多次提供
Iterator
的期望,而
Stream
无法实现。因此,虽然您可以从
Iterable
中创建
Stream
以供临时使用,但您必须小心是否可能存在多次迭代它的尝试。

既然你说,“我需要将字符串的这些部分作为

Iterable
传递到特定的库”,那么没有通用的解决方案,因为使用
Iterable
的代码超出了你的控制范围。

但是,如果您是创建流的人,则可以创建一个有效的

Iterable
,每次请求
Iterator
时,它都会简单地重复流构造:

Iterable<String> lines = () -> "this\nthat\nthe_other".lines().iterator();

这满足了支持任意次数迭代的期望,同时在仅遍历一次时不会比单个流消耗更多的资源。

for(var s: lines) System.out.println(s);
lines.forEach(System.out::println);
System.out.println(String.join("\n", lines));

15
投票

tl;博士

只需投射,无需转换。

Stream<String>::iterator
投射到
Iterable<String>

详情

注意请参阅Holger的回答解释使用流支持的危险

Iterable

是的,您可以用

Iterable
制作
Stream

解决方案很简单,但并不明显。请参阅这篇文章,了解 Maurice Naftalin 的 Lambda 常见问题解答

iterator
BaseStream
的超类)的
Stream
方法的签名返回
Iterator
与功能接口
Iterable
的唯一方法匹配,因此该方法参考
Stream<T>::iterator
可以用作
Iterable<T>
的实例。 (两种方法同名纯属巧合。)

提出您的意见。

String input = "this\n" +
        "that\n" +
        "the_other";
Stream<String> stream = input.lines() ;

使用方法参考生成

Iterable<String>

Iterable< String > iterable = stream::iterator;

测试结果。

for ( String s : iterable ) 
{
    System.out.println( "s = " + s );
}

查看此代码在 IdeOne.com 上实时运行

s = 这个

s = 那

s = the_other

警告谨防流支持的风险

Iterable
。在正确的Holger的回答中进行了解释。

© www.soinside.com 2019 - 2024. All rights reserved.