簡體   English   中英

RxJava:如何將對象列表轉換為另一個對象的列表

[英]RxJava: How to convert List of objects to List of another objects

我有 SourceObjects 列表,我需要將它轉換為 ResultObjects 列表。

我可以使用 ResultObject 的方法將一個對象提取到另一個對象:

convertFromSource(srcObj);

我當然可以這樣做:

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

但我將非常感謝可以展示如何使用rxJava做同樣事情的人

如果您的Observable發出一個List ,您可以使用這些運算符:

  • flatMapIterable (將您的列表轉換為一個 Observable 項目)
  • map (將您的項目轉換為另一個項目)
  • toList操作符(將一個完整的 Observable 轉換為一個 Observable,它從完整的 Observable 發出一個項目列表)

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

如果你想維護源Observable發出的Lists但轉換內容,即Observable<List<SourceObject>>Observable<List<ResultsObject>> ,你可以這樣做:

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

這確保了幾件事:

  • Observable發出的Lists數量保持不變。 即如果源發出 3 個列表,則另一端將有 3 個轉換后的列表
  • 使用Observable.fromIterable()將確保內部Observable終止,以便可以使用toList()

Observable.from()工廠方法允許您將對象集合轉換為 Observable 流。 一旦你有了一個流,你就可以使用map操作符來轉換每個發出的項目。 最后,您必須訂閱生成的 Observable 才能使用轉換后的項目:

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

如果您使用 lambda,則縮寫版本如下所示:

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

不要打破鏈條,就像這樣。

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

使用嵌套映射函數的非阻塞轉換

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

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

您可以使用地圖運算符。 例如,如果你有一個整數列表S和要轉換到雙打的名單S:

    List<Integer> li = new ArrayList<>();
    Observable.just(li).map( l -> {
        List<Double> lr = new ArrayList<Double>();
        for(Integer e:l) {
            lr.add(e.doubleValue());
        }
        return lr;
    });

但是,如果您可以控制 observable 並將其更改為觀察單個元素而不是集合,那就更自然了。 將單個整數元素轉換為雙整數元素的相同代碼:

Observable.just(1,2,3).map( elem -> elem.doubleValue())

作為Noel的擴展很好的答案。 假設轉換還取決於訂閱期間可能會更改的某些服務器數據。 在這種情況下,請使用flatMap + scan

因此,當 id 列表更改時,轉換將重新開始。 當與特定 id 相關的服務器數據發生變化時,單個項目也將被重新轉換。

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

使用 toList() 等待源 observable 完成,所以如果你在無限的 observable 上這樣做(比如綁定到 UI 事件和數據庫調用),你將永遠不會在你的 subscribe() 中得到任何東西。

解決方案是使用FlatMapSingleSwitchMapSingle

Observable<List<Note>> observable =   noteDao.getAllNotes().flatMapSingle(list -> Observable.fromIterable(list).toList());

現在,每次更新您的列表時,您都可以使該事件表現為可觀察的。

如果您需要的只是List<A>List<B>而不操作List<B>

最干凈的版本是:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM