2つのJava-8-Streamsを一緒に反復処理して、各反復ステップで2つの引数を持つようにしたいと思います。 somefunction
はStream<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つのストリームを同時に反復する別の方法はありますか?
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);
}
並列処理可能な圧縮が必要な場合は、Stream
のsourceを検討する必要があります。例えば。 2つのArrayList
s(または任意の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
を直接実装しない限り)