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


418

私はを返すインターフェイスを持っていますjava.lang.Iterable<T>

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

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

リストに変換せずにIterableをストリームとして使用する方法はありますか?


2
繰り返すことができる場合は、ループを単純に使用して、その条件または値をチェックするのはなぜですか?
Afzaal Ahmad Zeeshan 2014年

26
@AfzaalAhmadZeeshanストリームの方がはるかに優れているため
スレイマンジュネイジ2014年

1
私が言ったように、私はそのリスト(フィルター、マッピング)のいくつかの操作を行う必要があります。新しいJava 8 JDK API-> Streamを使用したいと思います。しかし、Iterableは「SteamAble」ではありません
レイマン

myIterable.stream()存在しない奇妙なようです!
Josh M.

7
@ギヨーム:はい、ただしがStream.of(iterable)生成されStream<Iterable<Object>>ます。
Matthias Braun

回答:


571

spliteratorUnknownSize直接使用するよりもはるかに良い答えがあります。これは簡単で、より良い結果を得ることができます。 Iterable持っているspliterator()あなたは自分のspliteratorを取得するためにそれを使用する必要がありますので、方法を。最悪の場合、それは同じコード(デフォルトの実装ではを使用spliteratorUnknownSize)ですが、より一般的なケースでは、Iterable既にコレクションである場合、より優れたスプリッターが得られるため、より優れたストリームパフォーマンスが得られます(おそらく並列処理も優れています)。また、コードも少なくなります。

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

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


109
上の静的メソッドはStreamいいでしょう、例えばStream.ofIterable(iterable)
robinst 2015

59
@robinstこれは省略ではありませんでした。それは意図的な(そして高度に議論された)選択でした。課題は、これが存在することであり、それに伴うトレードオフを理解せずに到達するのは簡単すぎることです。Iterableは非常に抽象的であるため、このようなメソッドを使用すると、パフォーマンスが最悪になる可能性があります(並列サポートなし、サイズ情報または特性なし(実行の選択を最適化するために使用))。より多くの思考を強制することは、エコシステム全体にわたってより良いAPIをもたらします。これは、「XYZコードに最適なもの」と「すべてのJavaコードに最適なもの」のトレードオフでした。
Brian Goetz 2016

2
あなたの説明に基づいて、Collection.stream()を取得したがIterable.stream()を取得しなかった理由を知りたいと思います。Iterable.stream()(またはStream.ofIterable())を省略する理由は、Collection.stream()にも同様に当てはまるようです。
2016


11
@BrianGoetzほとんどの人はあなたが上で言ったのを理解したり気にしないレベルにいないようです。単純なAPIを呼び出して単純なコードを記述したいだけです。一方、それらのこと(並列...)は、日常の反復可能な操作のほとんどにとって重要ではないかもしれません。
user_3380739 16


23

またはStreamから簡単に作成できます。IterableIterator

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

2
この関数を1回記述して、それを呼び出す必要があります。なぜstream(...)コードを散らかす呼び出しがあるのですか?
殺虫剤2014年

1
それをやりたかったインラインショートでエレガントな..ええ、私はこの関数を1回書くことができますが、私はコードをドロップします(コードを追加しない)。とにかくこの答えは正しいです。なぜなら、これがこれを変換する方法だからです。
レイマン2014年

静的インポートは関数を言った。短くエレガント。(必ずしも透明である必要はありません)
aepurniet 2014年

9

JOOLライブラリを使用することを勧めします。これは、Seq.seq(iterable)呼び出しの背後にスプリッターマジックを隠し、追加の便利な機能をすべて提供します。


7

したがって、別の回答が言及したように、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
  );
}

5

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

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)について考える必要がないため、完全に読みやすいと思います。


4

この問題の非常に簡単な回避策は、メソッドを保持する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>



-1

Java 8を使用し、外部ライブラリを使用しない別の方法:

Stream.concat(collectionA.stream(), collectionB.stream())
      .collect(Collectors.toList())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.