使用Java8JDK将Iterable转换为流

使用Java8JDK将Iterable转换为流,java,java-8,java-stream,iterable,Java,Java 8,Java Stream,Iterable,我有一个返回java.lang.Iterable的接口 我想使用Java8流API来处理这个结果 然而,Iterable不能“流” 您知道如何将Iterable用作流而不将其转换为List吗?您可以轻松地从Iterable或迭代器中创建流: publicstaticstream(Iterable-Iterable){ returnstreamsupport.stream( 拆分器。拆分器未知( iterable.iterator(), 分路器 ), 假的 ); } 有一个比直接使用拆分器或Unk

我有一个返回
java.lang.Iterable
的接口

我想使用Java8流API来处理这个结果

然而,Iterable不能“流”


您知道如何将Iterable用作流而不将其转换为List吗?

您可以轻松地从
Iterable
迭代器中创建

publicstaticstream(Iterable-Iterable){
returnstreamsupport.stream(
拆分器。拆分器未知(
iterable.iterator(),
分路器
),
假的
);
}

有一个比直接使用
拆分器或Unknownsize
更好的答案,它既简单又能获得更好的结果
Iterable
有一个
spliterator()
方法,所以您应该使用它来获取拆分器。在最坏的情况下,它是相同的代码(默认实现使用
spliterator unknownsize
),但在更常见的情况下,如果
Iterable
已经是一个集合,您将获得更好的spliterator,从而获得更好的流性能(甚至可能是良好的并行性)。它的代码也更少:

StreamSupport.stream(iterable.spliterator(), false)
             .filter(...)
             .moreStreamOps(...);

正如您所看到的,从
Iterable
(另请参阅)获取流不是很痛苦。

我建议使用库,它隐藏了
Seq.Seq(Iterable)
调用背后的拆分器魔法,还提供了一整套附加的有用功能。

我创建了这个类:

public class Streams {
    /**
     * Converts Iterable to stream
     */
    public static <T> Stream<T>  streamOf(final Iterable<T> iterable) {
        return toStream(iterable, false);
    }

    /**
     * Converts Iterable to parallel stream
     */
    public static <T> Stream<T> parallelStreamOf(final Iterable<T> iterable) {
        return toStream(iterable, true);
    }

    private static <T> Stream<T> toStream(final Iterable<T> iterable, final boolean isParallel) {
        return StreamSupport.stream(iterable.spliterator(), isParallel);
    }
}
公共类流{
/**
*将Iterable转换为流
*/
公共静态流(最终Iterable Iterable){
返回到流(iterable,false);
}
/**
*将Iterable转换为并行流
*/
公共静态流并行流(最终Iterable Iterable){
返回到流(iterable,true);
}
私有静态流到流(final Iterable Iterable,final boolean isParallel){
返回StreamSupport.stream(iterable.spliterator(),isParallel);
}
}

我认为它非常可读,因为您不必考虑拆分器和布尔值(isParallel)。

如果您可以使用Guava库,从版本21开始,您可以使用

Streams.stream(iterable)

解决此问题的一个非常简单的方法是创建一个扩展
Iterable
Streamable
接口,该接口包含一个
defaultstream()
方法

interface Streamable<T> extends Iterable<T> {
    default Stream<T> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}
接口可流扩展可流{
默认流(){
返回StreamSupport.stream(spliterator(),false);
}
}
现在,您的任何
Iterable
s都可以通过声明它们
implements streamable
而不是
Iterable

来实现可流化,如果您碰巧使用Vavr(以前称为Javaslang),这可以非常简单:

Iterable i = //...
Stream.ofAll(i);

因此,正如提到的另一个答案所述,Guava通过以下方式对此进行了支持:

Streams.stream(iterable);
我想强调的是,该实现与建议的其他答案略有不同。如果
Iterable
属于
Collection
类型,则会强制转换它

public static <T> Stream<T> stream(Iterable<T> iterable) {
  return (iterable instanceof Collection)
    ? ((Collection<T>) iterable).stream()
    : StreamSupport.stream(iterable.spliterator(), false);
}

public static <T> Stream<T> stream(Iterator<T> iterator) {
  return StreamSupport.stream(
    Spliterators.spliteratorUnknownSize(iterator, 0),
    false
  );
}
publicstaticstream(Iterable-Iterable){
返回(集合的iterable实例)
?((集合)iterable).stream()
:StreamSupport.stream(iterable.spliterator(),false);
}
公共静态流(迭代器迭代器){
returnstreamsupport.stream(
spliterator.spliteratorUnknownSize(迭代器,0),
假的
);
}

如果你可以迭代,为什么不简单地使用一个循环来检查它的条件或值,或者其他什么?@AfzaalAhmadZeeshan因为流比我说的要好得多,所以我需要在列表上做一些操作(过滤器、映射)。我想使用新的Java8JDKAPI->Stream。但是Iterable不是“可蒸的”,因为不存在
myIterable.stream()
,这看起来很奇怪@纪尧姆:是的,但是
Stream.of(iterable)
产生
Stream
。你必须编写这个函数一次,然后调用它。为什么对
stream(…)
的调用会使您的代码变得杂乱无章呢?希望以简洁优雅的方式内联完成。。你说得对,我可以写这个函数一次。。但我喜欢删除代码(而不是添加代码)。无论如何,这个答案是正确的,因为这是转换这个函数的方法。短小而优雅。(虽然不一定是透明的)在
上使用静态方法会很好,例如
Stream.ofIterable(iterable)
@robinst这不是一个遗漏;这是一个深思熟虑的选择(而且争论不休)。挑战在于,如果存在这种情况,在不了解随之而来的权衡的情况下,很容易达到目的。由于Iterable是如此抽象,这样的方法可能会导致性能最差的流(没有并行支持,没有大小信息或特征(用于优化执行选择))。强迫更多的思考会在整个生态系统中产生更好的API。这是“什么最适合XYZ代码”与“什么最适合所有Java代码”之间的折衷。根据您的解释,我很好奇为什么我们得到了Collection.stream(),而不是Iterable.stream()。省略Iterable.stream()(或stream.ofIterable())的理由似乎同样适用于Collection.stream()。@qualidafial-See@BrianGoetz看起来大多数人都不理解你上面所说的,或者根本不在乎。他们只想通过调用简单的API来编写简单的代码。另一方面,这些东西(并行…)可能对大多数日常iterable操作并不重要。或者,如果您停留在较旧的版本,请使用
列表。newArrayList(iterable)
。当前的Guava实现并不比公认的答案差: