Convert observable to list
Asked Answered
N

8

41

I am using RxJava.

I have an Observable<T>. How do I convert it to List<T>?

Seems to be a simple operation, but I couldn't find it anywhere on the net.

Nadabb answered 11/10, 2014 at 5:39 Comment(0)
P
25

You can use toList() or toSortedList() . For e.g.

observable.toList(myObservable)
          .subscribe({ myListOfSomething -> do something useful with the list });
Populace answered 11/10, 2014 at 6:22 Comment(2)
This doesn't convert it to a list. This is basically the same as if I have called subscribe.Nut
also note that toList() only creates the list when the sequence completes, so not useful for a long running streamSeyler
J
80
List<T> myList = myObservable.toList().toBlocking().single();
Jordanson answered 12/10, 2014 at 13:20 Comment(2)
it will result in blocking , not asynSlogan
@ZulqurnainJutt - did the toBlocking call give it away? (The question doesn't ask for it to be asynchronous)Amplification
P
25

You can use toList() or toSortedList() . For e.g.

observable.toList(myObservable)
          .subscribe({ myListOfSomething -> do something useful with the list });
Populace answered 11/10, 2014 at 6:22 Comment(2)
This doesn't convert it to a list. This is basically the same as if I have called subscribe.Nut
also note that toList() only creates the list when the sequence completes, so not useful for a long running streamSeyler
P
13

RxJava 2+:

List<T> = theObservarale
             .toList()
             .blockingGet();
Paries answered 30/6, 2017 at 14:35 Comment(1)
this returns only 1 size, kindly check my question here please : stackoverflow.com/q/49562033/3974048Markley
C
5

You can also use the collect operator:

    ArrayList list = observable.collect(ArrayList::new, ArrayList::add)
                               .toBlocking()
                               .single();

With collect, you can choose which type of Collection you prefer and perform an additional operation on the item before adding it to the list.

Chloechloette answered 1/10, 2017 at 17:7 Comment(2)
The collect could be written using method references as collect(ArrayList::new, ArrayList::add)Bitthia
Thanks for the tips, missed the use of method references here.Chloechloette
S
1

You can't convert observable to list in any idiomatic way, because a list isn't really a type that fits in with Rx.

If you want to populate a list with the events from a observable stream you need to basically create a list and add the items within a Subscribe method like so (C#):

IObservable<EventType> myObservable = ...;
var list = new List<EventType>();
myObservable.Subscribe(evt => list.Add(evt));

The ToList-style operators only provide a list once the stream completes (as an IObservable<List<T>>), so that isnt useful in scenarios where you have a long-lived stream or you want to see values before the stream completes.

Seyler answered 7/7, 2017 at 2:56 Comment(0)
E
1

This works.

public static void main(String[] args) {

    Observable.just("this", "is", "how", "you", "do", "it")
            .lift(customToList())
            .subscribe(strings -> System.out.println(String.join(" ", strings)));

}

public static <T> ObservableOperator<List<T>, T> customToList() {

    return observer -> new DisposableObserver<T>() {

        ArrayList<T> arrayList = new ArrayList<>();
        @Override
        public void onNext(T t) {
            arrayList.add(t);
        }

        @Override
        public void onError(Throwable throwable) {
            observer.onError(throwable);
        }

        @Override
        public void onComplete() {
            observer.onNext(arrayList);
            observer.onComplete();
        }
    };
}`
Electrolyte answered 9/3, 2020 at 23:26 Comment(0)
N
0

This might be a late answer, hope it helps somebody in future.

There is an operator collectInto(). I would suggest everyone to not use blocking() (unless in a test case) as you completely loose the purpose of async events in Rxchains. Try to chain your operations as much as possible

Completable setList(List<Integer> newIntegerList, Observable<Integer> observable){
   return observable.collectInto(newIntegerList, List::add).ignoreElement();
}

 // Can call this method
 Observable<Integer> observable = Observable.just(1, 2, 3);
 List<Integer> list = new ArrayList<>();
 setList(list, observable);

You save the hassle of using blocking() in this case.

Nonjoinder answered 18/12, 2018 at 12:1 Comment(0)
N
-11

Found it myself

public static <T> List<T> toList(Observable<T> observable) {
    final List<T> list = new ArrayList<T>();

    observable.toBlocking().forEach(new Action1<T>() {
        @Override
        public void call(T t) {
            list.add(t);
        }
    });

    return list;
}
Nadabb answered 11/10, 2014 at 10:59 Comment(2)
This is a bit of an anti-pattern. Use Observable.toList() instead, and make sure that the Observable is not infinite or you will have problems.Foreshadow
As Thomas sayed, you may want to reconsider accepting this one, that's not the way to do it.Sydelle

© 2022 - 2024 — McMap. All rights reserved.