RxJava flatMapIterable with a Single
Asked Answered
T

6

35

I'm trying to tidy up my code a little, and Single is looking like a good choice for me as I'm doing something that will only ever emit one result.

I'm having an issue though as I was using flatMapIterable previously to take my response (a list) and do something on each item. I'm not seeing how I can achieve this with Single.

getListOfItems()
.flatMapIterable(items -> items)
.flatMap(item -> doSomethingWithItem())
.toList()

This works fine if getListOfItems is returning an Observable but if I try and make it return a Single, then I can't do flatMapIterable and can't see an alternative, any ideas?

Transparency answered 14/3, 2017 at 12:1 Comment(0)
H
63

flattenAsObservable should do the trick, it will map Single success value to Iterable (list), and emit each item of the list as an Observable.

  getListOfItems()
            .flattenAsObservable(new Function<Object, Iterable<?>>() {
                @Override
                public Iterable<?> apply(@NonNull Object o) throws Exception {
                    return toItems(o);
                }
            })
            .flatMap(item -> doSomethingWithItem())
            .toList()
Hearthstone answered 14/3, 2017 at 13:11 Comment(4)
Thank you! This is what I was looking forTransparency
Single.flattenAsObservable doesn't exist. Was it a RxJava 1 thing? Is there a v2 equivalent?Sakti
@miguel, it's RxJava 2 only.Hearthstone
@Sakti it only exists for Single and Maybe. Not for Observable, Flowable or Completable.Hitoshi
D
15

Building on the answer from yosriz, this is what I ended up with in Kotlin

getListOfItems()
        .flattenAsObservable { it }
        .flatMap { doSomethingWithItem(it) }
        .toList()

The same can be achieved using Kotlin's map, depending on your preference:

getListOfItems()
        .map { items ->
            items.map {
                doSomethingWithItem(it)
            }
        }
Dubuffet answered 29/7, 2018 at 10:29 Comment(1)
In Kotlin you can even write getListOfItems().map { items -> items.map { doSomethingWithItem(it) } While the first map is from RxJava and operates on the stream emission, the second one is from Kotlin and operates on the Iterable.Hitoshi
D
5

You can convert Single to Observable by using operator toObservable()

It will look like this:

getListOfItems()
    .toObservable()
    .flatMapIterable(items -> items)
    .flatMap(item -> doSomethingWithItem())
    .toList()
Detrimental answered 6/4, 2018 at 8:32 Comment(0)
M
2

I've made something like this

@Override
public Single<List<String>> getAvailablePaths() {
        return mongoClient.rxFind("t_polygons", new JsonObject())
                            .toObservable()
                            .flatMapIterable(list -> list)
                            .map(json -> json.getString("path"))
                            .filter(Objects::nonNull)
                            .toList()
                            .toSingle();
    }
Maytime answered 7/11, 2017 at 10:23 Comment(0)
O
0

Another way to do it is by using flatMapPublisher and Flowable::fromIterable

getListOfItems()
    .flatMapPublisher(Flowable::fromIterable)
    .flatMap(item -> doSomethingWithItem())
    .toList()
Obstetric answered 28/2, 2019 at 11:24 Comment(0)
C
0
getListOfItems()
  .flattenAsObservable { it }
  .flatMapSingle { getSingleDoSomeThing(it) }
  .toList()
Connecticut answered 23/7, 2020 at 5:0 Comment(1)
This answer would be improved if you give an explanation of your code.Libertarian

© 2022 - 2024 — McMap. All rights reserved.