我对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个值)计算(计算所有值)花费更长的时间。
答案 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));
在这里,我分享该组并创建一个特殊输出;第一个元素与整个组结尾的串联(忽略元素)。