如何将 Stream 变成 Iterable?
How can I turn a Stream into an Iterable?
Stream
inherits an iterator() method to produce an Iterator
。
但我需要 Iterable
rather than an Iterator
。
例如,给定这个字符串:
String input = "this\n" +
"that\n" +
"the_other";
…我需要将字符串的这些部分作为 Iterable
传递给特定的库。调用 input.lines()
会产生 Stream
。因此,如果我可以将 Stream
变成其元素的 Iterable
,我就会确定。
tl;博士
直接投,无需转换
将 Stream<String>::iterator
转换为 Iterable<String>
。
详情
注意 请参阅 Holger 的回答,解释使用流支持的危险 Iterable
。
是的,你可以做一个Iterable
from a Stream
。
解决方案很简单,但并不明显。参见 this post on Maurice Naftalin's Lambda FAQ。
iterator
method of BaseStream
(superclass of Stream
) returning a Iterator
matches the only method of the functional interface 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 );
}
看到这个code run live at IdeOne.com。
s = this
s = that
s = the_other
注意事项 谨防流式支持的风险Iterable
。解释正确 .
如 Why does Stream<T> not implement Iterable<T>? 中所述,Iterable
期望能够多次提供 Iterator
,而 Stream
无法满足。因此,虽然您可以从 Stream
中创建一个 Iterable
以供临时使用,但您必须注意是否存在多次迭代它的尝试。
既然你说,“我需要将字符串的那些部分作为 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
inherits an iterator() method to produce an Iterator
。
但我需要 Iterable
rather than an Iterator
。
例如,给定这个字符串:
String input = "this\n" +
"that\n" +
"the_other";
…我需要将字符串的这些部分作为 Iterable
传递给特定的库。调用 input.lines()
会产生 Stream
。因此,如果我可以将 Stream
变成其元素的 Iterable
,我就会确定。
tl;博士
直接投,无需转换
将 Stream<String>::iterator
转换为 Iterable<String>
。
详情
注意 请参阅 Holger 的回答,解释使用流支持的危险 Iterable
。
是的,你可以做一个Iterable
from a Stream
。
解决方案很简单,但并不明显。参见 this post on Maurice Naftalin's Lambda FAQ。
iterator
method of BaseStream
(superclass of Stream
) returning a Iterator
matches the only method of the functional interface 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 );
}
看到这个code run live at IdeOne.com。
s = this
s = that
s = the_other
注意事项 谨防流式支持的风险Iterable
。解释正确
如 Why does Stream<T> not implement Iterable<T>? 中所述,Iterable
期望能够多次提供 Iterator
,而 Stream
无法满足。因此,虽然您可以从 Stream
中创建一个 Iterable
以供临时使用,但您必须注意是否存在多次迭代它的尝试。
既然你说,“我需要将字符串的那些部分作为 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));