将流转换为可迭代的流?tl;博士详

2022-09-01 08:51:58

Stream 继承一个迭代器() 方法来生成迭代

但我需要一个迭代器而不是迭代

例如,给定此字符串:

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

...我需要将字符串的这些部分作为 a 传递给特定的库。调用将生成 .因此,如果我能把它变成它的一个元素,我会被设定下来。Iterableinput.lines()StreamStreamIterable


答案 1

正如为什么 Stream<T> 不实现 Iterable<T>? 中所述,a 期望能够提供一次以上的,而 a 无法实现。因此,虽然您可以创建一个 out of a 用于临时使用,但您必须注意是否存在多次迭代它的尝试。IterableIteratorStreamIterableStream

既然你说,“我需要将字符串的这些部分作为可迭代传递给特定的库”,所以没有通用的解决方案,因为使用的代码超出了你的控制范围。Iterable

但是,如果您是创建流的人,则可以创建一个有效的,每次请求时都会简单地重复流构造:IterableIterator

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));

答案 2

tl;博士

只需投射,无需转换。

转换为 。Stream<String>::iteratorIterable<String>

谨慎请参阅霍尔格的答案解释使用流支持的危险。Iterable

是的,您可以从中进行可迭代

解决方案很简单,但不明显。请参阅Maurice Naftalin的Lambda FAQ上的这篇文章

返回迭代器BaseStreamStream 的超类)的迭代器方法的签名与功能接口 Iterable 的唯一方法匹配,因此方法引用可以用作 的实例。(两种方法具有相同的名称是巧合。Stream<T>::iteratorIterable<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


推荐