Je voudrais répéter deux Java-8-Streams ensemble, afin d'avoir à chaque étape de l'itération deux arguments. Quelque chose comme ça, où somefunction
produit quelque chose comme 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 ()));
Je veux savoir si Java fournit quelque chose comme ça, bien qu'il n'y ait pas de Pair
dans Java :-( S'il n'y a pas d'API) -Fonctionnement comme ça, existe-t-il une autre façon d'itérer deux flux simultanément?
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));
}
Cela n'offre pas une exécution parallèle, mais pas non plus l'implémentation d'origine Zip
.
Et comme F. Böller l'a souligné cela ne fonctionne pas si bs
est infini et as
ne l'est pas. Pour une solution qui fonctionne pour toutes les combinaisons possibles de flux infinis et finis, un Iterator
intermédiaire qui vérifie les deux sources dans la méthode hasNext
semble inévitable¹:
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);
}
Si vous voulez un zipping compatible parallèle, vous devriez considérer la source du Stream
. Par exemple. vous pouvez compresser deux ArrayList
s (ou n'importe quel RandomAccessList
) comme
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)))
. …
¹ (sauf si vous implémentez un Spliterator
directement)