Java 7环境下RxJava实现按邮政编码分组学生并统计距离总和
用RxJava在Java 7下实现Student按邮政编码分组并统计距离总和
嘿,这个需求在RxJava里完全可以搞定,而且适配Java 7的写法也不复杂,我给你一步步捋清楚怎么做:
首先,咱们先明确基础的Student类(按照你说的属性来):
public class Student { private String lastname; private String firstname; private String postalCode; // 这里假设是字符串类型,要是数字的话改成Integer就行 private int distance; // Java 7的构造器、getter方法,这里我就简写了 public Student(String lastname, String firstname, String postalCode, int distance) { this.lastname = lastname; this.firstname = firstname; this.postalCode = postalCode; this.distance = distance; } public String getPostalCode() { return postalCode; } public int getDistance() { return distance; } // 可选:重写toString方便调试 @Override public String toString() { return firstname + " " + lastname; } }
因为Java 7没有自带的键值对类,咱们可以自己写个简单的PostalCodeDistanceSum类来存分组后的结果:
public class PostalCodeDistanceSum { private String postalCode; private int totalDistance; public PostalCodeDistanceSum(String postalCode, int totalDistance) { this.postalCode = postalCode; this.totalDistance = totalDistance; } @Override public String toString() { return "邮政编码 " + postalCode + " 的总距离:" + totalDistance; } }
接下来就是核心的RxJava逻辑了,因为Java 7不支持Lambda,所以咱们得用匿名内部类实现各个Func接口:
import rx.Observable; import rx.functions.Func1; import rx.functions.Func2; public class StudentGroupingExample { public static void main(String[] args) { // 1. 创建模拟的学生数据源 Observable<Student> studentObservable = Observable.just( new Student("Smith", "John", "900", 150), new Student("Doe", "Jane", "900", 200), new Student("Brown", "Mike", "800", 100), new Student("Wilson", "Lisa", "900", 150), new Student("Taylor", "Bob", "800", 250) ); // 2. 分组并计算总和的核心逻辑 studentObservable // 按postalCode分组,得到每个分组的Observable .groupBy(new Func1<Student, String>() { @Override public String call(Student student) { return student.getPostalCode(); } }) // 对每个分组进行处理:计算distance总和,转成咱们定义的结果类 .flatMap(new Func1<Observable.GroupedObservable<String, Student>, Observable<PostalCodeDistanceSum>>() { @Override public Observable<PostalCodeDistanceSum> call(Observable.GroupedObservable<String, Student> groupedObservable) { final String postalCode = groupedObservable.getKey(); // 使用reduce累加每个分组的distance return groupedObservable.reduce(new Func2<Student, Student, Student>() { @Override public Student call(Student accumulated, Student current) { // 这里不需要保留学生信息,只需要累加距离,所以可以返回一个临时Student对象 return new Student("", "", postalCode, accumulated.getDistance() + current.getDistance()); } }) // 把累加后的结果转成PostalCodeDistanceSum .map(new Func1<Student, PostalCodeDistanceSum>() { @Override public PostalCodeDistanceSum call(Student student) { return new PostalCodeDistanceSum(postalCode, student.getDistance()); } }); } }) // 订阅输出结果 .subscribe(new rx.Observer<PostalCodeDistanceSum>() { @Override public void onCompleted() { System.out.println("所有分组统计完成"); } @Override public void onError(Throwable e) { System.err.println("处理出错:" + e.getMessage()); } @Override public void onNext(PostalCodeDistanceSum result) { System.out.println(result); } }); } }
关键步骤解释:
- groupBy操作符:它会把原始Observable中的Student按照postalCode分成多个
GroupedObservable,每个GroupedObservable的key就是对应的邮政编码,里面包含该组的所有Student对象。 - flatMap操作符:用来遍历每个分组的Observable,对每个分组单独处理。这里我们先获取分组的key(邮政编码),然后用reduce来累加距离。
- reduce操作符:它会遍历分组里的每个Student,把前一个累加的距离和当前Student的距离相加,最终得到该组的总距离。
- map操作符:把reduce得到的临时Student对象转换成我们需要的结果类,方便后续输出。
运行结果示例:
邮政编码 900 的总距离:500 邮政编码 800 的总距离:350 所有分组统计完成
如果你的postalCode是Integer类型,只需要把对应的泛型和getter返回值改成Integer就行,逻辑完全一致。另外,如果需要处理空的postalCode,可以在groupBy的Func里加个判断,比如返回一个默认值(比如"UNKNOWN"),避免出现null键的问题。
内容的提问来源于stack exchange,提问作者sameh
相关产品推荐
相关产品推荐

