Stream
继承一个iterator()方法来生成一个Iterator
.
例如,给定这个字符串:
String input = "this\n" +
"that\n" +
"the_other";
…我需要将字符串的这些部分作为Iterable
一个特定的库传递。调用input.lines()
产生一个Stream
. 所以如果我能把它Stream
变成Iterable
它的一个元素,我就会被设置。
Stream
继承一个iterator()方法来生成一个Iterator
.
例如,给定这个字符串:
String input = "this\n" +
"that\n" +
"the_other";
…我需要将字符串的这些部分作为Iterable
一个特定的库传递。调用input.lines()
产生一个Stream
. 所以如果我能把它Stream
变成Iterable
它的一个元素,我就会被设置。
正如为什么 Stream<T> 不实现 Iterable<T>?,anIterable
承担着能够提供Iterator
不止一次的 a 的期望,这是 aStream
无法实现的。因此,虽然您可以创建一个Iterable
out of aStream
以供临时使用,但您必须小心是否可能存在多次迭代它的尝试。
既然您说过,“<em>我需要将字符串的这些部分作为 anIterable
传递给特定的库”,因此没有通用的解决方案,因为使用的代码Iterable
超出了您的控制范围。
但是,如果您是创建流的人,则可以创建一个有效的Iterable
,它将在每次Iterator
请求 an 时简单地重复流构造:
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
。
解决方案很简单,但并不明显。请参阅Maurice Naftalin 的 Lambda FAQ上的这篇文章。
返回 a的(superclass of )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 );
}
s = 这个
s = 那
s = the_other
CAVEAT谨防流式支持的风险Iterable
。Holger在正确答案中进行了解释。