Creating a Cartesian product asynchronously is difficult or, in a sense, impossible. And if the lock is ok, you can do something like this
public class Main
{
static class ProductIterator<T> implements Iterator<T[]>
{
private final List<List<T>> componentsList;
private final Class<T> componentClass;
private final int[] indices;
private boolean hasNext;
public ProductIterator(List<List<T>> componentsList, Class<T> componentClass)
{
this.componentsList = componentsList;
this.componentClass = componentClass;
this.indices = new int[componentsList.size()];
this.hasNext = this.indices[componentsList.size() - 1] < componentsList.get(componentsList.size() - 1).size();
}
@Override
public boolean hasNext()
{
return hasNext;
}
@Override
public T[] next()
{
T[] res = (T[]) Array.newInstance(componentClass, componentsList.size());
for (int i = 0; i < componentsList.size(); i++)
{
res[i] = componentsList.get(i).get(indices[i]);
}
indices[0]++;
for (int i = 0; i < componentsList.size() - 1; i++)
{
if (indices[i] == componentsList.get(i).size())
{
indices[i] = 0;
indices[i + 1]++;
}
}
hasNext = indices[componentsList.size() - 1] < componentsList.get(componentsList.size() - 1).size();
return res;
}
}
public static <T> Observable<T[]> product(Observable<Observable<T>> components, Class<T> componentClass)
{
return Observable.fromIterable(new Iterable<T[]>()
{
@Override
public Iterator<T[]> iterator()
{
Single<List<List<T>>> componentsList = components.map(o -> o.toList().blockingGet()).toList();
return new ProductIterator<T>(componentsList.blockingGet(), componentClass);
}
});
}
public static void main(String[] args) throws Exception
{
Observable<Observable<Integer>> ob = Observable.just(
Observable.just(0, 1),
Observable.just(2, 3),
Observable.just(4, 5)
);
Observable<Integer[]> product = product(ob, Integer.class);
product.forEach(a -> System.out.println(Arrays.toString(a)));
}
}
, , Observable, . , , - .