web-dev-qa-db-ja.com

Java 8 JDKを使用してIterableをStreamに変換

Java.lang.Iterable<T>を返すインターフェースがあります。

その結果をJava 8 Stream APIを使用して操作したいと思います。

しかしIterableは「ストリーミング」できません。

どのようにそれをListに変換せずにIterableをStreamとして使用するかについての任意のアイデア?

368
rayman

spliteratorUnknownSizeを直接使用するよりもはるかに良い答えがあります。これはどちらもより簡単でより良い結果を得ます。 Iterablespliterator()メソッドを持っているので、あなたはあなたのspliteratorを得るためにそれを使うべきです。最悪の場合、それは同じコードです(デフォルトの実装はspliteratorUnknownSizeを使用します)が、あなたのIterableがすでにコレクションであるもっと一般的なケースでは、あなたはより良いspliterator、そしてより良いストリームパフォーマンスを得ます)コードも少なくなります。

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

ご覧のとおり、Iterableからストリームを取得すること( この質問 も参照)はそれほど苦痛ではありません。

506
Brian Goetz

バージョン21以降、Guavaライブラリを使用できる場合は、次のものを使用できます。

Streams.stream(iterable)
55
numéro6

StreamまたはIterableからIteratorを簡単に作成できます。

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

_ jool _ libraryを使用することをお勧めします。これはSeq.seq(iterable)呼び出しの背後にあるspliteratorの魔法を隠し、さらに便利な機能をたくさん提供します。

9
Shaggie

私はこのクラスを作成しました:

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

あなたはspliteratorsとbooleans(isParallel)について考える必要がないので、私はそれが完全に読みやすいと思います。

3
g-t

この問題に対する非常に簡単な回避策は、default <T> stream()メソッドを保持するStreamable<T>を拡張するIterable<T>インターフェースを作成することです。

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

Iterable<T>の代わりにimplements Streamable<T>を宣言するだけで、どんなIterable<T>も簡単にストリーミングできるようになります。

3
OldCurmudgeon

別の答えが述べたように、グアバはこれをサポートしています:

Streams.stream(iterable);

私は、実装は他の答えが提案したものとは少し違うことをしていることを強調したい。 IterableCollection型の場合、それらはそれをキャストします。

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

たまたまVavr(以前のJavaslangとして知られている)を使用するなら、これは同じくらい簡単でありえます:

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