rxJava变换List to Map

时间:2015-11-20 02:16:41

标签: android rx-java

我有一个从REST端点返回的列表。我需要将该列表分解为类别(类别是列表的每个条目中的项目)。各个类别将写入缓存,以便以后更快地查找。

我不知道是否可以.map()条目并提供多个filter()或某种类型的case语句,以便将类别条目放入正确的存储桶中。

使用rxJava实现这样的事情是否合理?

更新: 非工作版

private Map<String, List<VideoMetadataInfoEntity>> buildCategories( Observable<List<VideoMetadataInfoEntity>> videoList ) {

    Map<String, List<VideoMetadataInfoEntity>> categoryMap = new HashMap<>();
    videoList
            .flatMap( Observable::from )
            .subscribe( videoMetadataInfoEntity -> mapCategory(videoMetadataInfoEntity, categoryMap ) );

    Observable.just( categoryMap )
            .doOnNext( saveCategoriesToCacheAction );

    return categoryMap;
}

然而,这些是按顺序触发的,这是我的理解,第二个observable没有发送任何saveCategoriesToCacheAction,因为它没有订阅第一个observable的结果。

我开始认为我应该修改我的缓存策略。该列表将始终包含所有详细信息。该服务并未提供我可用于列出的子集,然后是另一个调用以获取完整详细信息。它是一个项目的完整列表或完整详细信息。现在,将每个单独缓存到自己的类别缓存中可能是一种更好的方法。我正在尝试执行映射,以便此网络调用可以返回请求的类别,但后续调用将来自缓存,直到缓存已过期并且新的网络调用刷新它。

3 个答案:

答案 0 :(得分:3)

我的解决方案是:

Observable.range(1, 20)
            .groupBy(number -> number % 2)
            .flatMap(groupedObservable -> groupedObservable.toList())
            .toMap(list -> list.get(0) % 2);

因此我有[{0=[2, 4, 6, 8, 10, 12, 14, 16, 18, 20], 1=[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]}]

说明:

  • range(1,20) - 创建一个可观察到的前20个数字
  • groupBy(number - &gt; number%2) - 创建一个发出组observable的observable,其中每个group observable包含使用分组函数分组的项目(此处为x%2)
  • flatMap(groupedObservable - &gt; groupedObservable.toList()) - 将每个组转换为一个可以将所有项目作为列表发布的observable
  • toMap(list - &gt; list.get(0)%2) - 创建地图

答案 1 :(得分:0)

RxJava更适用于异步消息处理,但由于它还支持函数式编程原则,因此它可以用作穷人的流api。如果您使用的是Java 8,请考虑使用流来完成这项工作,但是当您提出这个问题时,我假设您使用的是Java 7。

要做你想做的事你可以尝试(原谅lambda,如果你没有使用Retrolambda,用一个匿名的内部类替换它):

Observable.from(list).subscribe(item -> groupItemInCategoryBucket(item));

其中groupItemInCategoryBucket是包含switch语句的方法,或者您缓存项目的其他方式。

请注意,这相当于for循环,虽然在许多其他好的语言中使用这种风格是惯用的,但许多Java开发人员在看到这段代码时可能会有些困惑。

答案 2 :(得分:0)

通常可以使用groupBy运算符来实现项目分组(有关它的更多信息,请访问this page)。

Map<Integer, List<Integer>> groupedValues = new HashMap<>(4);
    Observable.range(1, 20)
            .groupBy(i -> i % 2, i -> i)
            .subscribe(go -> {
                List<Integer> groupValues = new ArrayList<>();
                groupedValues.put(go.getKey(), groupValues);
                go.subscribe(t -> add(t, groupValues));
            });

工作原理:

  • 首先,observable发出第1到第20项(这种情况发生在range方法中)
  • 然后根据它们将哪些可观察物分开 奇偶校验(groupBy方法,在此方法之后运行GroupedObservable
  • 然后,您订阅了分组的observable,接收(在订阅者onNext中)单独的可观察项,其中包含分组项目和按其分组的密钥。
  • 如果他们的内容对您不感兴趣以防止内存泄漏,请记住订阅已分组的observable或在其上发出take(0)

    我不确定这是否是最有效的方式,并欢迎对此解决方案的一些意见。