RxJava实现:将SourceObject列表按名称分组转换为ResultObject列表
Got it, let's break down how to solve this problem step by step. You need to group SourceObject instances by their name field, merging all related grades into a single ResultObject per name—plus integrate this logic with RxJava's Single stream type. Let's dive in.
Core Logic Overview
First, the key task is two-fold:
- Group all
SourceObjects by theirnamevalue - Convert each group into a
ResultObject, where thegradeslist holds all grades from that group
We'll use Java 8's Stream API for grouping/mapping, paired with RxJava operators to handle the reactive stream.
Solution for Single<List<SourceObject>> Input
Assuming your input is a Single wrapping a list of SourceObjects (since you mentioned having a list of these objects), here's a complete implementation:
import io.reactivex.rxjava3.core.Single; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class ObjectTransformer { public Single<List<ResultObject>> transformSourceToResult(Single<List<SourceObject>> sourceSingle) { return sourceSingle .map(sourceList -> { // Step 1: Group SourceObjects by their name field Map<String, List<SourceObject>> groupedByName = sourceList.stream() .collect(Collectors.groupingBy(SourceObject::getName)); // Step 2: Convert each group to a ResultObject return groupedByName.entrySet().stream() .map(entry -> { ResultObject result = new ResultObject(); result.setName(entry.getKey()); // Extract all grades from the group and assign to ResultObject List<String> grades = entry.getValue().stream() .map(SourceObject::getGrade) .collect(Collectors.toList()); result.setGrades(grades); return result; }) .collect(Collectors.toList()); }); } }
Key Notes
- Make sure your
SourceObjectandResultObjectclasses have public getter/setter methods for their private fields (e.g.,getName(),getGrade()forSourceObject,setName(),setGrades()forResultObject—otherwise the code won't compile). - If the input list is empty, the output will be an empty list of
ResultObjects. - Duplicate
namevalues will be merged into oneResultObject, with grades preserved in the order they appeared in the input list.
Adjustment for Observable<SourceObject> Input
If your input is actually a stream of individual SourceObjects (instead of a list wrapped in Single), you can use RxJava's groupBy operator to handle grouping on the fly:
import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Single; import java.util.List; import java.util.stream.Collectors; public class ObjectTransformer { public Single<List<ResultObject>> transformSourceToResult(Observable<SourceObject> sourceObservable) { return sourceObservable .groupBy(SourceObject::getName) .flatMapSingle(group -> group .map(SourceObject::getGrade) .toList() .map(grades -> { ResultObject result = new ResultObject(); result.setName(group.getKey()); result.setGrades(grades); return result; })) .toList(); } }
This version processes each SourceObject as it emits, groups them by name, and merges the grades into a ResultObject for each group.
内容的提问来源于stack exchange,提问作者gaurav miglani

