Stream
继承了 iterator() 方法来生成 Iterator
。
Iterable
而不是Iterator
。
例如,给定这个字符串:
String input = "this\n" +
"that\n" +
"the_other";
…我需要将字符串的这些部分作为
Iterable
传递到特定的库。调用 input.lines()
会产生 Stream
。因此,如果我可以将 Stream
变成其元素的 Iterable
,我就确定了。
正如为什么 Stream
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));
只需投射,无需转换。
将
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的回答中进行了解释。