Преобразование наблюдаемого в список

Я использую RxJava.

У меня есть Observable<T>. Как преобразовать его в List<T>?

Вроде простая операция, но нигде в сети не нашел.


person Khanh Nguyen    schedule 11.10.2014    source источник


Ответы (8)


Вы можете использовать toList() или toSortedList() . Например,

observable.toList(myObservable)
          .subscribe({ myListOfSomething -> do something useful with the list });
person sol4me    schedule 11.10.2014
comment
Это не преобразует его в список. Это в основном то же самое, как если бы я позвонил subscribe. - person Adam Arold; 28.03.2016
comment
также обратите внимание, что toList() создает список только после завершения последовательности, поэтому бесполезен для длительного потока - person Jack Ukleja; 07.07.2017

Надеюсь это поможет.

List<T> myList = myObservable.toList().toBlocking().single();

спасибо

Ананд Раман

person diduknow    schedule 12.10.2014
comment
это приведет к блокировке, а не к асинхронности - person Zulqurnain Jutt; 19.01.2017
comment
@ZulqurnainJutt - вызов toBlocking выдал это? (Вопрос не требует, чтобы он был асинхронным) - person Nick Cardoso; 18.01.2018

RxJava 2+:

List<T> = theObservarale
             .toList()
             .blockingGet();
person Andrew    schedule 30.06.2017
comment
это возвращает только 1 размер, пожалуйста, проверьте мой вопрос здесь, пожалуйста: stackoverflow.com/q/49562033/3974048 - person david; 29.03.2018

Вы также можете использовать оператор collect:

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

С помощью collect вы можете выбрать тип Collection, который вы предпочитаете, и выполнить дополнительную операцию над элементом перед добавлением его в список.

person araknoid    schedule 01.10.2017
comment
Сбор может быть записан с использованием ссылок на методы как collect(ArrayList::new, ArrayList::add) - person Will; 26.01.2018
comment
Спасибо за советы, пропустил использование ссылок на методы здесь. - person araknoid; 26.01.2018

Вы не можете преобразовать observable в список каким-либо идиоматическим способом, потому что список на самом деле не тот тип, который подходит для Rx.

Если вы хотите заполнить список событиями из наблюдаемого потока, вам нужно в основном создать список и добавить элементы в метод Subscribe, например так (C#):

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

Операторы в стиле ToList предоставляют список только после завершения потока (как IObservable<List<T>>), поэтому это бесполезно в сценариях, где у вас есть долгоживущий поток или вы хотите увидеть значения до завершения потока.

person Jack Ukleja    schedule 07.07.2017

Это работает.

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();
        }
    };
}`
person edmangini76    schedule 09.03.2020

Это может быть поздний ответ, надеюсь, что это поможет кому-то в будущем.

Есть оператор collectInto(). Я бы посоветовал всем не использовать blocking() (кроме тестового случая), так как вы полностью теряете цель асинхронных событий в Rxchains. Старайтесь максимально связать свои операции

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);

В этом случае вы избавляете себя от необходимости использовать blocking().

person Shubham Srivastava    schedule 18.12.2018

Сам нашел

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;
}
person Khanh Nguyen    schedule 11.10.2014
comment
Это немного анти-паттерн. Вместо этого используйте Observable.toList() и убедитесь, что Observable не бесконечно, иначе у вас возникнут проблемы. - person tmn; 30.08.2015
comment
Как сказал Томас, вы можете подумать над тем, чтобы принять это, это не способ сделать это. - person tokland; 06.11.2015