繁体   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