使用 Java 8 JDK 将 Iterable 转换为 Stream

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23932061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 09:09:49  来源:igfitidea点击:

Convert Iterable to Stream using Java 8 JDK

javajava-8java-streamiterable

提问by rayman

I have an interface which returns java.lang.Iterable<T>.

我有一个返回java.lang.Iterable<T>.

I would like to manipulate that result using the Java 8 Stream API.

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

However Iterable can't "stream".

但是 Iterable 不能“流”。

Any idea how to use the Iterable as a Stream without converting it to List?

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

采纳答案by Brian Goetz

There's a much better answer than using spliteratorUnknownSizedirectly, which is both easier and gets a better result. Iterablehas a spliterator()method, so you should just use that to get your spliterator. In the worst case, it's the same code (the default implementation uses spliteratorUnknownSize), but in the more common case, where your Iterableis already a collection, you'll get a better spliterator, and therefore better stream performance (maybe even good parallelism). It's also less code:

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

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

As you can see, getting a stream from an Iterable(see also this question) is not very painful.

如您所见,从Iterable(另请参阅此问题)获取流并不是很痛苦。

回答by nosid

You can easily create a Streamout of an Iterableor Iterator:

您可以轻松地创建Stream出一个IterableIterator

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

回答by Shaggie

I would like to suggest using JOOLlibrary, it hides spliterator magic behind the Seq.seq(iterable) call and also provides a whole bunch of additional useful functionality.

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

回答by g-t

I've created this class:

我创建了这个类:

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

I think it's perfectly readable because you don't have to think about spliterators and booleans (isParallel).

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

回答by numéro6

If you can use Guava library, since version 21, you can use

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

Streams.stream(iterable)

回答by OldCurmudgeon

A very simple work-around for this issue is to create a Streamable<T>interface extending Iterable<T>that holds a default <T> stream()method.

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

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

Now any of your Iterable<T>s can be trivially made streamable just by declaring them implements Streamable<T>instead of Iterable<T>.

现在,您Iterable<T>的任何s 都可以通过声明它们implements Streamable<T>而不是Iterable<T>.

回答by Grzegorz Piwowarek

If you happen to use Vavr(formerly known as Javaslang), this can be as easy as:

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

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

回答by Alex

So as another answer mentioned Guava has support for this by using:

因此,正如另一个答案所提到的,番石榴通过使用以下方法对此提供支持:

Streams.stream(iterable);

I want to highlight that the implementation does something slightly different than other answers suggested. If the Iterableis of type Collectionthey cast it.

我想强调的是,该实现与建议的其他答案略有不同。如果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
  );
}

回答by Greg Witczak

Another way to do it, with Java 8 and without external libs:

另一种方法,使用 Java 8 而没有外部库:

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