简体   繁体   English

将2个RxJava Observables转换为1个地图

[英]Transform 2 RxJava Observables to 1 Map

I have following scenario. 我有以下情况。 I'm getting data from server using Retrofit2. 我正在使用Retrofit2从服务器获取数据。 I want to download Collection<Account> of Account entities, and for each of those accounts to download Collection<Project> of Project entities. 我要下载Account实体的Collection<Account> ,然后为每个帐户下载Project实体的Collection<Project> At the end I want to get Map<Account, Collection<Project>> accountsWithProjects . 最后,我想获取Map<Account, Collection<Project>> accountsWithProjects

I have following methods: 我有以下方法:

  1. Observable<Collection<Account>> requestAllAccounts()
  2. Observable<Collection<Project>> requestProjectsInfoForTempoAccount(Account accunt)

Question: Is it possible to zip or create somehow foreach iteration of these two reactive streams and collect all the items to the map? 问题:是否可以压缩或以某种方式为这两个反应流的每次迭代创建并收集所有项目到地图上?

I can also get the collection of projects for account synchronously if it helps, however can't do it on main thread, since developing for Android and the result must be observed on main thread. 如果有帮助,我也可以同步获取帐户的项目集合,但是不能在主线程上完成,因为针对Android开发并且必须在主线程上观察结果。

There you have it: 你有它:

requestAllAccounts().flatMap(new Func1<Collection<Account>, Observable<Account>>() {
        @Override
        public Observable<Account> call(Collection<Account> accountCollection) {
            return Observable.from(accountCollection);
        }
    }).flatMap(new Func1<Account, Observable<Pair<Account, Collection<Project>>>>() {
        @Override
        public Observable<Pair<Account, Collection<Project>>> call(Account account) {
            return Observable.just(account).zipWith(requestProjectsInfoForTempoAccount(account),
                    new Func2<Account, Collection<Project>, Pair<Account, Collection<Project>>>() {
                        @Override
                        public Pair<Account, Collection<Project>> call(Account account, Collection<Project> projects) {
                            return new Pair<Account, Collection<Project>>(account, projects);
                        }
                    });
        }
    }).toList()
            .flatMap(new Func1<List<Pair<Account, Collection<Project>>>, Observable<Map<Account, Collection<Project>>>>() {
                @Override
                public Observable<Map<Account, Collection<Project>>> call(List<Pair<Account, Collection<Project>>> pairs) {
                    Map<Account, Collection<Project>> map = new HashMap<Account, Collection<Project>>();
                    for (Pair<Account, Collection<Project>> pair : pairs) {
                        map.put(pair.first, pair.second);
                    }
                    return Observable.just(map);
                }
            });

What is going on here? 这里发生了什么?

  1. Get all accounts. 获取所有帐户。
  2. Split list into single accounts 将列表拆分为单个帐户
  3. Invoke searching for projects on single account and return the Pair<Account, Collection<Project>> 调用在单个帐户上搜索项目,然后返回Pair<Account, Collection<Project>>
  4. Merge all objects 合并所有对象
  5. Transform List<Pair<Account, Collection<Project>>> to Map<Account, Collection<Project>> List<Pair<Account, Collection<Project>>>Map<Account, Collection<Project>>

Here's a better way: 这是一个更好的方法:

requestAllAccounts()
.flatMap(account -> requestProjectsInfoForTempoAccount(account),
   (acccount, projects) -> Pair::of)
.toMap(Pair::key, Pair::value);

(expansion to Java 7 left as an excercise for the reader) (扩展到Java 7作为练习供读者使用)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM