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 of itemsに変換します)map
(アイテムを別のアイテムに変換)toList
演算子(完成したObservableを、完成したObservableからアイテムのリストを出力するObservableに変換します)
Observable<SourceObjet> source = ...
source.flatMapIterable(list -> list)
.map(item -> new ResultsObject().convertFromSource(item))
.toList()
.subscribe(transformedList -> ...);
ソースLists
から発行されたObservable
を維持したいが、内容、つまり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 -> ...);
これにより、いくつかのことが保証されます。
Lists
から放出されるObservable
の数は維持されます。つまり、ソースが3つのリストを発行する場合、もう一方の端には3つの変換されたリストがありますObservable.fromIterable()
を使用すると、toList()
を使用できるように、内側のObservable
が終了することが保証されます。Observable.from() factoryメソッドを使用すると、オブジェクトのコレクションを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
}
});
ラムダを使用する場合の短縮バージョンは次のようになります。
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.
});
必要なものが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();
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)
}
}
}
ネストされたマップ関数を使用した非ブロック変換
val ints: Observable<List<Int>> = Observable.fromArray(listOf(1, 2, 3))
val strings: Observable<List<String>> = ints.map { list -> list.map { it.toString() } }