如何链接多个RxJava的groupBy()方法,例如groupBy()。groupBy()

时间:2015-01-30 07:14:19

标签: java android rx-java reactive-programming

给定输入:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

将数字分组为奇数或偶数,然后小于或大于5。

预期产出:

[[1, 3, 5], [2, 4], [6, 8, 10], [7, 9]]

输出的顺序不受限制。

我现在使用以下方法:

Observable.range(1, 10)
    .groupBy(n -> n % 2 == 0)
    .flatMap((GroupedObservable<Boolean, Integer> g) -> {
        return Observable.just(g).flatMap(ObservableUtils.<Boolean, Integer>flatGroup()).groupBy(n -> n > 5);
    })
    .subscribe((final GroupedObservable<Boolean, Integer> g) -> {
        Observable.just(g).flatMap(ObservableUtils.<Boolean, Integer>flatGroup()).forEach(n -> println(g + ": " + n));
    });

请注意,ObservableUtils是我编写的,用于简化代码。

但我对此并不满意,因为它仍然不够短,只能表明目标。

我的期望如下:

Observable.range(1, 10)
    .groupBy(n -> n % 2 == 0)
    .groupBy(n -> n > 5)
    .subscribe(...);

现在我只能把它缩小为:

Observable.range(1, 10)
    .lift(new OperatorGroupByGroup(n -> n % 2 == 0))
    .lift(new OperatorGroupByGroup(n -> n > 5))
    .subscribe(...);

我仍然需要编写稍微复杂的OperatorGroupByGroup类。有任何改善的建议吗?

3 个答案:

答案 0 :(得分:2)

我为OperatorGroupByGroup编写了一个基于OperatorGroupBy的示例:

https://github.com/yongjhih/RxJava-GroupByTest

用法:

git clone https://github.com/yongjhih/RxJava-GroupByTest.git
./gradlew execute

但是由于我的OperatorGroupByGroup实现,我修改了测试代码:

    Observable.range(1, 10)
    .lift(new OperatorGroupByGroup<Integer, Boolean, Integer>(n -> n % 2 == 0))
    .lift(new OperatorGroupByGroup<GroupedObservable<Boolean, Integer>, Boolean, Integer>(n -> n > 5))
    .subscribe((final GroupedObservable<Boolean, Integer> g) -> {
        Observable.just(g).flatMap(ObservableUtils.<Boolean, Integer>flatGroup()).forEach(n -> println(g + ": " + n));
    });

我认为有人会做得更好。

答案 1 :(得分:2)

尝试以这种方式做到。

Observables.range(1,10)
  .groupBy( n -> n % 2 == 0)
  .flatMap( grp -> grp.groupBy( n -> n > 5).flatMap( grp2 -> grp2.toList()))
  .subscribe(...)

答案 2 :(得分:1)

我有两个建议,我认为它们都非常简洁和优雅。

首先:

Observable.range(1, 10)
    .groupBy(n -> n % 2 == 0)
    .flatMap(g -> g.groupBy(n -> n > 5))
    .subscribe(...);

这几乎与您的期望一样好,只需增加一个.flatMap()。唯一的问题?你失去了第一把钥匙,但我不确定你是否正在使用它们。

第二个需要声明一个简单的Key类,它可以保存两个条件的结果,并且具有正确的equals()实现。换句话说,Pair。然后你可以这样做:

Observable.range(1, 10)
    .groupBy(n -> new Key(n % 2 == 0, n > 5))
    .subscribe(...);

这样做的缺点是组合性较差,因为在同一个.groupBy()调用中有两个条件而不是链接。优点是,如果需要,您可以使用组合键来保存两个条件的结果。