wake-up-neo.net

RxJava: Wie konvertiert man Liste der Objekte in Liste anderer Objekte?

Ich habe die Liste der SourceObjects und muss sie in die Liste der ResultObjects konvertieren.

Ich kann ein Objekt mit einer Methode von ResultObject zu einem anderen Objekt abrufen:

convertFromSource(srcObj);

natürlich kann ich es so machen:

public void onNext(List<SourceObject> srcObjects) {
   List<ResultsObject> resObjects = new ArrayList<>();
   for (SourceObject srcObj : srcObjects) {
       resObjects.add(new ResultsObject().convertFromSource(srcObj));
   }
}

ich bin jedoch sehr dankbar für jemanden, der mit rxJava dasselbe tun kann.

46
Yura Buyaroff

Wenn Ihre Observable eine List ausgibt, können Sie diese Operatoren verwenden:

  • flatMapIterable (verwandeln Sie Ihre Liste in ein beobachtbares Element)
  • map (verwandeln Sie Ihren Artikel in einen anderen Artikel) 
  • toList-Operatoren (wandeln Sie ein abgeschlossenes Observable in ein Observable um, das eine Liste von Elementen aus dem abgeschlossenen Observable ausgibt)

    Observable<SourceObjet> source = ...
    source.flatMapIterable(list -> list)
          .map(item -> new ResultsObject().convertFromSource(item))
          .toList()
          .subscribe(transformedList -> ...);
    
60
dwursteisen

Wenn Sie die Lists beibehalten möchten, die von der Quelle Observable ausgegeben wird, aber den Inhalt konvertieren möchten, d. H. Observable<List<SourceObject>> in Observable<List<ResultsObject>>, können Sie Folgendes tun:

Observable<List<SourceObject>> source = ...
source.flatMap(list ->
        Observable.fromIterable(list)
            .map(item -> new ResultsObject().convertFromSource(item))
            .toList()
            .toObservable() // Required for RxJava 2.x
    )
    .subscribe(resultsList -> ...);

Dies stellt einige Dinge sicher:

  • Die von Lists ausgegebene Anzahl von Observable wird beibehalten. d.h. wenn die Quelle 3 Listen ausgibt, gibt es am anderen Ende 3 transformierte Listen
  • Durch die Verwendung von Observable.fromIterable() wird sichergestellt, dass die innere Observable beendet wird, sodass toList() verwendet werden kann
40
Noel

Mit der Methode Observable.from () factory können Sie eine Sammlung von Objekten in einen Observable-Stream konvertieren. Nachdem Sie einen Stream erstellt haben, können Sie den ausgegebenen Artikel mit dem Operator map transformieren. Schließlich müssen Sie das resultierende Observable abonnieren, um die transformierten Elemente verwenden zu können:

// Assuming List<SourceObject> srcObjects
Observable<ResultsObject> resultsObjectObservable = Observable.from(srcObjects).map(new Func1<SourceObject, ResultsObject>() {
    @Override
    public ResultsObject call(SourceObject srcObj) {
        return new ResultsObject().convertFromSource(srcObj);
    }
});

resultsObjectObservable.subscribe(new Action1<ResultsObject>() { // at this point is where the transformation will start
    @Override
    public void call(ResultsObject resultsObject) { // this method will be called after each item has been transformed
        // use each transformed item
    }
});

Die abgekürzte Version, wenn Sie Lambdas verwenden, würde folgendermaßen aussehen:

Observable.from(srcObjects)
  .map(srcObj -> new ResultsObject().convertFromSource(srcObj))
  .subscribe(resultsObject -> ...);
11
murki

Brechen Sie die Kette nicht einfach so.

Observable.from(Arrays.asList(new String[] {"1", "2", "3", }))
.map(s -> Integer.valueOf(s))
.reduce(new ArrayList<Integer>, (list, s) -> {
    list.add(s);
    return list;
})
.subscribe(i -> {
    // Do some thing with 'i', it's a list of Integer.
});
4
AtanL

Wenn Sie lediglich List<A> bis List<B> benötigen, ohne das Ergebnis von List<B> zu ändern,.

Die sauberste Version ist:

List<A> a = ... // ["1", "2", ..]
List<B> b = Observable.from(a)
                      .map(a -> new B(a))
                      .toList()
                      .toBlocking()
                      .single();
0
saiday

Als Erweiterung zu Noel tolle Antwort. Nehmen wir an, die Umwandlung hängt auch von einigen Serverdaten ab, die sich während des Abonnements ändern können. In diesem Fall verwenden Sie flatMap + scan.

Wenn sich die ID-Liste ändert, werden die Umwandlungen neu gestartet. Wenn sich Serverdaten in Bezug auf eine bestimmte ID ändern, werden auch einzelne Elemente erneut übertragen. 

fun getFarmsWithGroves(): Observable<List<FarmWithGroves>> {

        return subscribeForIds() //may change during subscription
                .switchMap { idList: Set<String> ->

                    Observable.fromIterable(idList)
                            .flatMap { id: String -> transformId(id) } //may change during subscription
                            .scan(emptyList<FarmWithGroves>()) { collector: List<FarmWithGroves>, candidate: FarmWithGroves ->
                                updateList(collector, candidate)
                            }
                }
    }
0
Andrew

Nicht blockierende Konvertierung mit verschachtelter Kartenfunktion

val ints: Observable<List<Int>> = Observable.fromArray(listOf(1, 2, 3))

val strings: Observable<List<String>> = ints.map { list -> list.map { it.toString() } }
0
tomrozb