[英]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() 中得到任何東西。
解決方案是使用FlatMapSingle或SwitchMapSingle 。
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.