white-imp
white-imp

Reputation: 323

RxJava: how to use Observable instead nested loops?

Now I use nested loops with ReplaySubject to get multiple observables and this need to be converted without using any loops, just observables.

private Observable<BaseUnit> getUnitObservables(ArrayList<Map<Integer, Integer>> list, ReplaySubject<BaseUnit> subject) {

    ArrayList<Observable<BaseUnit>> observables = new ArrayList<>();
    
    for (Map<Integer, Integer> elem : list) {
        for (MapOperationName operationName : MapOperationName.values()) { // MapOperationName type is enum

            Observable<BaseUnit> observable = Observable.fromCallable(() -> {
                // some operations here

                subject.onNext(unit);
                observables.add(observable);
            });
        }
    }
    return Observable.merge(observables);
}

"Map<Integer, Integer> elem : list" has 3 elements. "MapOperationName.values()" return 7 elements. So totally should be 21 as I get in example above.

Trying to refactor something like this but get only 3 elements:

private Observable<BaseUnit> getUnitObservables(ArrayList<Map<Integer, Integer>> list, ReplaySubject<BaseUnit> subject) {

    Observable<ListOperationName> observableOperation = 
    Observable.fromArray(MapOperationName.values());
    Observable<List<Integer>> observableList = Observable.fromIterable(list);
    return Observable.zip(observableList, observableOperation, (listElem, operationElem) -> {

        subject.onNext(unit);
        //some operations here
    });

}

How to combine correctly this ArrayList and Enum to get full set of pair combination?

Upvotes: 2

Views: 430

Answers (2)

bubbles
bubbles

Reputation: 2717

I'm not really fun of passing a ReplaySubject to your method. Instead you can turn your method as a source and let your subject subscribe to it :

private Observable<BaseUnit> getUnitObservables(ArrayList<Map<Integer, Integer>> list) {
    return Observable.fromIterable(list)
            .flatMap(listElem -> Observable.fromArray(MapOperationName.values())
                    .map(operationElem -> {
                        // some operations here
                        return new BaseUnit();
                    })
            );
}

...
...

Subject<BaseUnit> subject = ReplaySubject.create();
subject
        .mergeWith(getUnitObservables(listParam))
        .subscribe();

Upvotes: 1

dano
dano

Reputation: 94881

You can nest the operations you need to do inside of a flatMap to achieve this:

private Observable<BaseUnit> getUnitObservables(ArrayList<Map<Integer, Integer>> list, ReplaySubject<BaseUnit> subject) {

    Observable<ListOperationName> observableOperation = 
        Observable.fromArray(MapOperationName.values());
    Observable<List<Integer>> observableList = Observable.fromIterable(list);
    return observableList
        .flatMap(listElem -> observableOperation
            .map(operationElem -> {
                // some operations here
                subject.onNext(unit);
                return unit;  // Assuming unit is a BaseUnit
            })
        );
}

Upvotes: 3

Related Questions