使用Java 8 JDK将Iterable转换为Stream

时间:2014-05-29 11:16:28

标签: java java-8 java-stream iterable

我有一个返回java.lang.Iterable<T>的接口。

我想使用Java 8 Stream API来操作该结果。

但是Iterable不能“流”。

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

9 个答案:

答案 0 :(得分:508)

与直接使用spliteratorUnknownSize相比,这是一个更好的答案,这既容易又获得更好的结果。 Iterable有一个spliterator()方法,因此您应该使用它来获取分词符。在最糟糕的情况下,它是相同的代码(默认实现使用spliteratorUnknownSize),但在更常见的情况下,您的Iterable已经是一个集合,您将获得一个更好的分裂器,因此更好的流性能(甚至可能是良好的并行性)。它的代码也少了:

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

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

答案 1 :(得分:56)

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

Streams.stream(iterable)

答案 2 :(得分:22)

您可以轻松地从StreamIterable创建Iterator

public static <T> Stream<T> stream(Iterable<T> iterable) {
    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize(
            iterable.iterator(),
            Spliterator.ORDERED
        ),
        false
    );
}

答案 3 :(得分:9)

我想建议使用JOOL库,它隐藏了Seq.seq(可迭代)调用背后的分裂器魔法,并提供了一大堆额外的有用功能。

答案 4 :(得分:3)

我创建了这个类:

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

我认为它完全可读,因为你不必考虑分裂器和布尔值(isParallel)。

答案 5 :(得分:3)

解决此问题的一个非常简单的方法是创建一个Streamable<T>扩展Iterable<T>接口,其中包含default <T> stream()方法。

interface Streamable<T> extends Iterable<T> {
    default Stream<T> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}

现在,只需将Iterable<T>声明为implements Streamable<T>而不是Iterable<T>,您的任何@Transactional都可以轻松制作流媒体。

答案 6 :(得分:3)

因此,另一个答案提到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
  );
}

答案 7 :(得分:0)

如果你碰巧使用Vavr(以前称为Javaslang),这可以很简单:

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

答案 8 :(得分:-2)

使用Java 8并且没有外部库的另一种方法:

Stream.concat(collectionA.stream(), collectionB.stream())
      .collect(Collectors.toList())