Reputation: 604
Having below class
class Train {
String type;
List<RateInfo> rateInfos;
}
want to groupBy type and needs to return as List
rateType will be AC, general, VIP
Here I am grouping by rateType.
Map<String, List<RateInfo>> collect
= rateInfos.stream()
.collect(Collectors.groupingBy(RateInfo::getRateType));
Instead of collecting as Map<String, List<RateInfo>>
, I want to collect it as List<Train>
.
the List<Train>
will have always 3 elements(based on rateType
)
for example:
[rateType:"AC", roomTypeInfos: [n nmuber of values], rateType:"general", roomTypeInfos: [n nmuber of values], rateType:"economy", roomTypeInfos: [n nmuber of values]]
how to transform it?
Upvotes: 1
Views: 795
Reputation: 19545
Class Train
may be updated with a constructor accepting a RateInfo
parameter. and a merge function needs to be implemented.
Also, merge
function needs to be implemented to add appropriate RateInfo
to the list in the current instance of Train
.
@Data
@AllArgsConstructor
class Train {
String type;
List<RateInfo> rateInfos;
public Train(RateInfo rate) {
this(rate.rateType, new ArrayList<>());
this.rateInfos.add(rate);
}
public Train merge(Train that) {
this.rateInfos.addAll(that.rateInfos);
return this;
}
}
Then it could be convenient to use Collectors::collectingAndThen
along with Collectors::toMap
to build a map with rateType
key, and convert to the List<Train>
:
List<RateInfo> rateInfos = Arrays.asList(
new RateInfo("AC", 200),
new RateInfo("AC", 300),
new RateInfo("General", 400),
new RateInfo("General", 500),
new RateInfo("General", 750),
new RateInfo("VIP", 800),
new RateInfo("VIP", 1000)
);
List<Train> merged = rateInfos.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(RateInfo::getRateType, Train::new, Train::merge, LinkedHashMap::new), // Map<String, Train> created here
map -> new ArrayList<>(map.values()) // from Collection<Train>
));
merged.forEach(System.out::println);
Output:
Train(type=AC, rateInfos=[RateInfo(rateType=AC, rate=200), RateInfo(rateType=AC, rate=300)])
Train(type=General, rateInfos=[RateInfo(rateType=General, rate=400), RateInfo(rateType=General, rate=500), RateInfo(rateType=General, rate=750)])
Train(type=VIP, rateInfos=[RateInfo(rateType=VIP, rate=800), RateInfo(rateType=VIP, rate=1000)])
Upvotes: 1
Reputation: 4935
I think each grouping is to be mapped into a Train
object.
Create a constructor for the Train
class with type
and the list passed as arguments. Then update your current code as:
// This generates a List<Train>
rateInfos.stream()
.collect(Collectors.groupingBy(RateInfo::getRateType))
.entrySet()
.map(entry -> new Train(entry.getKey(), entry.getValue())
.collect(Collectors.toList());
Upvotes: 1