简体   繁体   English

RxJava - 将列表和请求转换为地图

[英]RxJava - convert list and request into map

I have a list of "Parent" objects and I want to get a "Child" list for each of them. 我有一个“父”对象列表,我希望每个对象都有一个“子”列表。 I want as result a map of Parent and Child list. 我想要一个父子列表的地图。 So the result is 结果是

Map<Parent, List<Child>> result = new HashMap<>();

My sample Parent list: 我的示例父列表:

List<Parent> parents = new ArrayList<>();
parents.add(new Parent(1, "Parent1"));
parents.add(new Parent(2, "Parent2"));
parents.add(new Parent(3, "Parent3"));
parents.add(new Parent(4, "Parent4"));
parents.add(new Parent(5, "Parent5"));

I want to iterate them and ask children one by one 我想迭代他们并逐一问孩子们

 @GET("api/childs/{parentId}")
 Observable<Response<List<Child>>> getChilds(@Path("parentId") int parentId);

What is the best RX structure for this? 什么是最好的RX结构?

Thank you, Robert 谢谢罗伯特

Observable.from(parents)
    .concatMap(p -> getChilds(p.getId())
        .map(Response::getValue)
        .map(children -> Pair.of(p, children)))
    .toMap(Pair::getLeft, Pair::getRight)

Where Pair is a simple wrapper of two value left and right . 其中Pair是二值的简单包装leftright

The implementation that I thought of is along these lines: 我想到的实现是这样的:

Iterate through the parents, and for each try to form a Map.Entry with the children by using flatMap() . 遍历父项,并尝试使用flatMap()与子项形成Map.Entry Then you can collect them into a Map . 然后你可以将它们收集到一张Map The code looks like this: 代码如下所示:

public static void main(String[] args) {

    List<Parent> parents = new ArrayList<>();
    parents.add(new Parent(1, "Parent1"));
    parents.add(new Parent(2, "Parent2"));
    parents.add(new Parent(3, "Parent3"));
    parents.add(new Parent(4, "Parent4"));
    parents.add(new Parent(5, "Parent5"));

    Single<Map<Parent, List<Child>>> result = Observable.fromIterable(parents)
            .flatMap(getMapEntries())
            .toMap(keySelector(), valueSelector());
}

private static Function<Parent, Observable<Map.Entry<Parent, List<Child>>>> getMapEntries() {
    return new Function<Parent, Observable<Map.Entry<Parent, List<Child>>>>() {
        @Override
        public Observable<Map.Entry<Parent, List<Child>>> apply(Parent parent) throws Exception {
            return getChilds(parent.getId())
                    .map(extractResponse())
                    .map(createMapEntry(parent));
        }
    };
}

private static Function<Response<List<Child>>, List<Child>> extractResponse() {
    return new Function<Response<List<Child>>, List<Child>>() {

        @Override
        public List<Child> apply(Response<List<Child>> listResponse) throws Exception {
            return listResponse.body();
        }
    };
}

private static Function<List<Child>, Map.Entry<Parent, List<Child>>> createMapEntry(Parent parent) {
    return new Function<List<Child>, Map.Entry<Parent, List<Child>>>() {
        @Override
        public Map.Entry<Parent, List<Child>> apply(List<Child> children) throws Exception {
            return new AbstractMap.SimpleImmutableEntry<>(parent, children);
        }
    };
}

private static Function<Map.Entry<Parent, List<Child>>, Parent> keySelector() {
    return new Function<Map.Entry<Parent, List<Child>>, Parent>() {
        @Override
        public Parent apply(Map.Entry<Parent, List<Child>> parentListEntry) throws Exception {
            return parentListEntry.getKey();
        }
    };
}

private static Function<Map.Entry<Parent, List<Child>>, List<Child>> valueSelector() {
    return new Function<Map.Entry<Parent, List<Child>>, List<Child>>() {
        @Override
        public List<Child> apply(Map.Entry<Parent, List<Child>> parentListEntry) throws Exception {
            return parentListEntry.getValue();
        }
    };
}

However, you should also handle errors for your Response . 但是,您还应该处理Response错误。 You can do it in extractResponse() , by throwing an exception for instance. 您可以通过抛出异常来在extractResponse()执行此操作。

Btw, the plural for child is children . 顺便说一句, child的复数是children

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

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