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

时间:2016-03-01 21:39:01

标签: java android rx-java

我有SourceObjects列表,我需要将它转换为ResultObjects列表。

我可以使用ResultObject方法将一个对象提取到另一个对象:

--

当然我可以这样做:

convertFromSource(srcObj);

但我会非常感谢能够使用 rxJava 来展示如何做同样事情的人。

9 个答案:

答案 0 :(得分:63)

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

答案 1 :(得分:48)

如果您想维护来源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()将确保内部Observable终止,以便toList()可以使用

答案 2 :(得分:11)

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

答案 3 :(得分:4)

不要破坏链条,就像这样。

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

答案 4 :(得分:1)

使用toList()等待可观察的源代码完成,因此,如果您对一个无限的可观察对象(例如与UI事件和数据库调用绑定的对象)执行此操作,则您的Subscribe()中将永远不会得到任何东西。

解决方案是使用 FlatMapSingle SwitchMapSingle

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

现在,每次更新列表时,您都可以使该事件的行为可观察到。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

作为Noel好答案的扩展。 假设转换还取决于订阅期间可能更改的某些服务器数据。在这种情况下,请使用 flatMap + 扫描

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

答案 7 :(得分:0)

使用嵌套映射功能进行非阻塞转换

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

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

答案 8 :(得分:-1)

您可以使用map运算符。例如,如果您有整数列表 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并将其改为观察单个元素而不是集合,那么所有这一切都更自然。将单个整数元素转换为double整数的相同代码:

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