我有下面的课程,我已经创建,以说明我的疑问。
在我的可流动的初始变换后,我有:
UserScoreTO{id=1, name='john', score=4}
UserScoreTO{id=1, name='john', score=5}
UserScoreTO{id=1, name='john', score=1}
UserScoreTO{id=2, name='paul', score=4}
UserScoreTO{id=2, name='paul', score=2}
UserScoreTO{id=3, name='mark', score=1}
UserScoreTO{id=3, name='mark', score=7}
我希望将具有相同ID的UserScoreTO对象组合到一个Flowable中,为每个组发出一个单独的对象,其中包含用户信息和分数总和。
因此结果将是可流动的,发出:
User (1, "john", 10);
User (2, "paul", 6);
User (3, "mark", 8);
如果可能的话,我想用RxJava做这个(我知道我可以用HashMaps做同样的事情)。
package examples.rxjava;
import java.util.Arrays;
import java.util.List;
import io.reactivex.Flowable;
import static java.lang.System.out;
public class TestUsers {
public static void main(String[] args) {
new TestUsers().execute();
}
public void execute() {
getUsers()
.flatMap(list -> Flowable.fromIterable(list))
.groupBy(userScoreTO -> userScoreTO.id).subscribe(group -> group.subscribe(out::println));
}
Flowable<List<UserScoreTO>> getUsers() {
return Flowable.fromCallable(
() -> Arrays.asList(
new UserScoreTO(1, "john", 4),
new UserScoreTO(1, "john", 5),
new UserScoreTO(1, "john", 1),
new UserScoreTO(2, "paul", 4),
new UserScoreTO(2, "paul", 2),
new UserScoreTO(3, "mark", 1),
new UserScoreTO(3, "mark", 7))
);
}
private class User {
private int id;
private String name;
private int totalScore;
public User(int id, String name, int totalScore) {
this.id = id;
this.name = name;
this.totalScore = totalScore;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", totalScore=" + totalScore +
'}';
}
}
private class UserScoreTO {
private int id;
private String name;
private int score;
public UserScoreTO(int id, String name, int score) {
this.id = id;
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "UserScoreTO{" +
"id=" + id +
", name='" + name + '\'' +
", score=" + score +
'}';
}
}
}
答案 0 :(得分:1)
您提供的代码已经完全符合您的要求。 groupBy会将具有相同id的UserScoreTO对象分组到同一个GroupedFlowable对象中。
修改强>
好的,我知道,也许以下内容可以做得更好一点
public void execute() {
getUsers()
.flatMap(Flowable::fromIterable)
.groupBy(userScoreTO -> userScoreTO.id)
.map(group -> group.reduce(new User(group.getKey(), "", 0),
(user, userScoreTO) -> {
user.name = userScoreTO.name;
user.totalScore += userScoreTO.score;
return user;
}))
.subscribe(userSingle -> userSingle.subscribe(System.out::println));
}
您想要的是通过应用reduce运算符将UserScoreTo聚合到同一个User对象中。
答案 1 :(得分:1)
在做了一些研究并做了大量的试错代码后,我发现这个[collect][1]
运算符可以解决问题:
它创建一个新的User对象(User::new
)作为初始供应商,该供应商保存来自组中所有项目的数据。所以我设置属性并增加分数,在组迭代结束时返回它。
由于我是RxJava的新手,我不知道这是否是最好的方法,或者代码是否可以简化,但结果代码是:
getUsers()
.flatMap(list -> Flowable.fromIterable(list))
.groupBy(userScoreTO -> userScoreTO.id)
.flatMap(groups -> Flowable.fromCallable(() -> groups.collect(User::new, (user, userscore) -> {
user.id = userscore.id;
user.name = userscore.name;
user.totalScore += userscore.score;
}))).subscribe(userSingle -> {
userSingle.subscribe(new SingleObserver<User>() {
@Override
public void onSubscribe(Disposable d) {
System.out.println("onSubscribe");
}
@Override
public void onSuccess(User user) {
System.out.println(user);
}
@Override
public void onError(Throwable e) {
System.out.println(e);
}
});
});
输出:
onSubscribe
onSubscribe
onSubscribe
User{id=1, name='john', totalScore=10}
User{id=2, name='paul', totalScore=6}
User{id=3, name='mark', totalScore=8}