web-dev-qa-db-ja.com

2つのJava-8-Streamsを一緒に反復する

2つのJava-8-Streamsを一緒に反復処理して、各反復ステップで2つの引数を持つようにしたいと思います。 somefunctionStream<Pair<A,B>>のようなものを生成します。

Stream<A> as;
Stream<B> bs;
somefunction (as, bs)
  .forEach ((a, b) -> foo (a, b));
// or something like
somefunction (as, bs)
  .forEach ((Pair<A, B> abs) -> foo (abs.left (), abs.right ()));

Javaはそのようなものを提供しますが、JavaにPairはありませんが、APIがない場合-そのような機能、2つのストリームを同時に反復する別の方法はありますか?

29
F. Böller
static <A, B> Stream<Pair<A, B>> Zip(Stream<A> as, Stream<B> bs)
{
    Iterator<A> i=as.iterator();
    return bs.filter(x->i.hasNext()).map(b->new Pair<>(i.next(), b));
}

これは並列実行を提供しませんが、元のZip実装も提供しませんでした。

そして F。Böllerが指摘したようにbsが無限でasがそうでない場合は機能しません。無限ストリームと有限ストリームのすべての可能な組み合わせで機能するソリューションの場合、Iteratorメソッド内の両方のソースをチェックする中間hasNextは避けられないようです¹:

static <A, B> Stream<Pair<A,B>> Zip(Stream<A> as, Stream<B> bs) {
    Iterator<A> i1 = as.iterator();
    Iterator<B> i2 = bs.iterator();
    Iterable<Pair<A,B>> i=()->new Iterator<Pair<A,B>>() {
        public boolean hasNext() {
            return i1.hasNext() && i2.hasNext();
        }
        public Pair<A,B> next() {
            return new Pair<A,B>(i1.next(), i2.next());
        }
    };
    return StreamSupport.stream(i.spliterator(), false);
}

並列処理可能な圧縮が必要な場合は、Streamsourceを検討する必要があります。例えば。 2つのArrayLists(または任意のRandomAccessList)を次のように圧縮できます

ArrayList<Foo> l1=new ArrayList<>();
ArrayList<Bar> l2=new ArrayList<>();
IntStream.range(0, Math.min(l1.size(), l2.size()))
         .mapToObj(i->new Pair(l1.get(i), l2.get(i)))
         . …

¹(Spliteratorを直接実装しない限り)

24
Holger