Reputation: 73251
I'm having a problem figuring out the right way to stream and collect my data.
The stream is the following
public List<List<CalculatedItemCostPerStore>> getCalcualtedItemCostPerStore() {
var it = item
.getQuantities().stream().map(quantities -> {
Store.StoreCosts<CostType, BigDecimal> storeCosts = quantities.getStore().getStoreCosts();
return new CalculatedItemCostPerStore(quantities.getStore().getName(), new TreeSet<>(quantities
.getItemCostEvents()
.stream()
.map(e -> new CalculatedItemCost(e.getCostTrigger(), e.getTriggerQuantity().multiply(storeCosts.get(e.getCostTrigger()))))
.collect(
Collectors.toMap(CalculatedItemCost::getCostType, Function.identity(), (a, b) -> new CalculatedItemCost(a.getCostType(), a.getCost().add(b.getCost())))
).values()));
}).collect(Collectors.groupingBy(CalculatedItemCostPerStore::getStore)).values().stream().collect(Collectors.toList());
return it;
}
Get's streamed into
@Data
@AllArgsConstructor
static class CalculatedItemCost implements Comparable<CalculatedItemCost> {
private CostType costType;
private BigDecimal cost;
@Override
public int compareTo(CalculatedItemCost o) {
return this.costType.toString().compareTo(o.getCostType().toString());
}
}
@Data
@AllArgsConstructor
static class CalculatedItemCostPerStore {
private String store;
private TreeSet<CalculatedItemCost> calculatedItemCosts;
}
and itemCostEvents are a list of
{
"createdAt": "2018-08-29T00:00:00",
"costTrigger": "STORAGE_COST_PER_CBM_PER_DAY",
"triggerQuantity": 33
}
above stream creates a result that is represented by below json. As you can see it's an List<List<CalculatedItemCostPerStore>>
"calcualtedItemCostPerStore": [
[
{
"store": "foo",
"calculatedItemCosts": [
{
"costType": "ADDITIONAL_COST_OFFICE_PER_HOUR",
"cost": 1368
},
{
"costType": "STORAGE_COST_PER_CBM_PER_DAY",
"cost": 287.1
}
]
}
],
[
{
"store": "bar",
"calculatedItemCosts": [
{
"costType": "ADDITIONAL_COST_OFFICE_PER_HOUR",
"cost": 38
}
]
}
]
]
There can be any number of occurrences of quantities, of which each can have one store.
What I would like to get is a single List<CalculatedItemCostPerShop>
like shown below
"calcualtedItemCostPerStore": [
{
"store": "foo",
"calculatedItemCosts": [
{
"costType": "ADDITIONAL_COST_OFFICE_PER_HOUR",
"cost": 1368
},
{
"costType": "STORAGE_COST_PER_CBM_PER_DAY",
"cost": 287.1
}
]
},
{
"store": "bar",
"calculatedItemCosts": [
{
"costType": "ADDITIONAL_COST_OFFICE_PER_HOUR",
"cost": 38
}
]
}
]
How would I need to adapt my stream to get above result?
Upvotes: 2
Views: 91
Reputation: 73251
Solved it thanks to @ernest_k - using flatMap
on the .values()
public List<CalculatedItemCostPerStore> getCalcualtedItemCostPerStore() {
return item
.getQuantities().stream().map(quantities -> {
Store.StoreCosts<CostType, BigDecimal> storeCosts = quantities.getStore().getStoreCosts();
return new CalculatedItemCostPerStore(quantities.getStore().getName(), new TreeSet<>(quantities
.getItemCostEvents()
.stream()
.map(e -> new CalculatedItemCost(e.getCostTrigger(), e.getTriggerQuantity().multiply(storeCosts.get(e.getCostTrigger()))))
.collect(
Collectors.toMap(CalculatedItemCost::getCostType, Function.identity(), (a, b) -> new CalculatedItemCost(a.getCostType(), a.getCost().add(b.getCost())))
).values()));
})
.collect(Collectors.groupingBy(CalculatedItemCostPerStore::getStore))
.values()
.stream()
.flatMap(Collection::stream).collect(Collectors.toList())
;
}
Upvotes: 1