使用RxJava获取GroupedObservable的第一个元素

时间:2016-07-01 14:10:15

标签: rx-java

我对RxJava很新。

我正在尝试按给定键对元素进行分组,并获取每个键的第一个值。

例如,按照第一个字母对这些名称进行分组,并为每个组打印第一个名称:

Observable<String> names = Observable.just(
                             "John", "Steve", "Ruth",
                             "Sam", "Jane", "James");

这是我到目前为止所尝试的内容:

第一次尝试

names.groupBy(s -> s.charAt(0))
     .flatMap(grp -> grp.first())
     .subscribe(s -> System.out.println(s));

FAILED!:打印所有名称。

第二次尝试

names.groupBy(s -> s.charAt(0))
     .subscribe(grp -> grp
                         .first()
                         .subscribe(System.out::println));

再次失败!:所有名字仍然打印出来......

我设法通过减少每个GroupedObservable来获得预期的结果:

第一次尝试,使用reduce

names.groupBy(s -> s.charAt(0))
     .flatMap(grp -> grp.reduce((a, b) -> a))
     .subscribe(s -> System.out.println(s));

第二次尝试,使用reduce

names.groupBy(s -> s.charAt(0))
     .subscribe(grp -> grp
                         .reduce((a, b) -> a)
                         .subscribe(System.out::println));

但这种解决方案并不理想。在现实世界中,这将涉及一些昂贵的计算,并且reduce()运算符将比first()运算符(通过键仅计算1个值)计算(计算所有值)花费更长的时间。

1 个答案:

答案 0 :(得分:5)

这是由groupBy的属性引起的:如果某个组被取消(不再被观察),则可能会启动具有相同密钥的新组。这里first取消订阅第一个元素后,具有相同键的后续元素重新创建该组。

您可以通过一些publish欺骗来阻止这种情况:

Observable<String> names = Observable.just(
        "John", "Steve", "Ruth",
        "Sam", "Jane", "James");

names.groupBy(s -> s.charAt(0))
.flatMap(grp -> grp.publish(o -> o.first().concatWith(o.ignoreElements())))
.subscribe(s -> System.out.println(s));

在这里,我分享该组并创建一个特殊输出;第一个元素与整个组结尾的串联(忽略元素)。