android RxJava:如何将对象列表转换为另一个对象列表

dzhpxtsq  于 2022-12-21  发布在  Android
关注(0)|答案(9)|浏览(194)

我有一个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做同样的事情,我将非常感激。

dojqjjoe

dojqjjoe1#

如果您需要的只是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();
x3naxklr

x3naxklr2#

如果Observable发出List,则可以使用以下运算符:

  • flatMapIterable(将列表转换为可观察项)
  • map(将您的项目转换为其他项目)
  • toList操作符(将一个完整的可观测对象转换为一个可观测对象,该可观测对象从完整的可观测对象中发出一个项目列表)
Observable<SourceObjet> source = ...
source.flatMapIterable(list -> list)
      .map(item -> new ResultsObject().convertFromSource(item))
      .toList()
      .subscribe(transformedList -> ...);
oymdgrw7

oymdgrw73#

如果你想保留源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()
eimct9ow

eimct9ow4#

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

如果你使用lambdas,缩写版本将如下所示:

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

lx0bsm1f5#

别把链子弄断,就像这样。

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

7cwmlq896#

使用嵌套Map函数的非分块转换

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

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

ycl3bljg7#

作为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)
                            }
                }
    }
ssm49v7z

ssm49v7z8#

使用toList()会等待源观察对象完成,因此如果您对无限的观察对象(如绑定到UI事件和Database调用的观察对象)执行此操作,您将永远无法在subscribe()中获得任何内容。
此问题的解决方案是使用FlatMapSingleSwitchMapSingle

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

现在,每当列表更新时,您可以将该事件作为可观察事件。

2skhul33

2skhul339#

您可以使用map运算符。例如,如果您有整数的lists,并且您希望转换为双精度的lists

List<Integer> integers = new ArrayList<>();
    Observable.just(integers).map(values -> {
        List<Double> doubles = new ArrayList<Double>();
        for(Integer i: values) {
            doubles.add(i.doubleValue());
        }
        return doubles;
    });

但如果你能控制可观察的事物,并将其改变为观察单个元素而不是集合,那就更自然了,同样的代码可以将单个整数元素转换为双精度元素:

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

相关问题