Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJava: execute a list of Single in parallel and get the results in a list in the same order

I have a list of network calls to do (they return a Single<Item>), and I want to execute them all in parallel. Once all the calls are successful, I'd like to get a List<Item>, in the same order as the List<Single<Item>>.

I've managed to do it and it works, but it seems a bit too complicated, and I am guessing there must be a simpler way to do as this seems to be a pretty common use case?

Here's what I did:

    List<Single<Pair<Item, Integer>>> itemSingles = new ArrayList<>();
    for (int index = 0; index < itemCount - 1; index++) {
        int finalIndex = index;
        itemSingles.add(
                fetchItem(...)
                .map(item -> new Pair<>(item, finalIndex))
        );
    }

    Single.merge(itemSingles)
            .sorted((o1, o2) -> o1.second.compareTo(o2.second))
            .map(itemPair -> itemPair.first)
            .toList()
            .subscribe(items -> { ... });

As you can see I have to use Pair<Item, Integer> to bind each item with its position, and then later I can sort using the position.

Any simpler way?

like image 309
BoD Avatar asked Feb 24 '18 16:02

BoD


Video Answer


1 Answers

Use concatMapEager():

 Flowable.range(0, itemCount)
     .concatMapEager(index -> 
         fetchItem(index)
         .subscribeOn(Schedulers.io())
         .toFlowable(),
         /* max parallel executions: */ 8,
         /* items expected per source: */ 1
     )
     .toList();
like image 184
akarnokd Avatar answered Oct 11 '22 14:10

akarnokd