I have a Car
POJO:
class Car
{
String make;
int year;
BigDecimal amount;
}
And a List<Car>
of cars such as that:
make : year : price
honda : 2011 : $20,000
honda : 2011 : $30,000
honda : 2012 : $50,000
ford : 2012 : $12,000
Where I want to have as a result:
// Map<make, List<year, totalForYear>>
Map<String, Map<int, BigDecimal>> revenuesByMakeAndYear;
How can I achieve this with Streams? So far I'm halfway with:
// Map<make, List<car>>
Map<String, List<Car>> carsByMake = cars.stream()
.collect(Collectors.toMap(
car -> car.getMake(),
car -> cars.stream()
.filter(subCar -> subCar.getMake().equals(car.getMake())
.collect(Collectors.toList())));
But how do I get to the next step?
You can use nested groupingBy
to group by make and year, and then reducing
to produce the total revenue):
Map<String,Map<Integer,BigDecimal>> totals =
cars.stream ()
.collect (Collectors.groupingBy (c->c.make,
Collectors.groupingBy (c->c.year,
Collectors.reducing (new BigDecimal(0),
c->c.amount,
BigDecimal::add))));
If the property you wish to sum wasn't a BigDecimal
, you could have replaced reducing
with the simpler summingInt
or summingLong
or summingDouble
.
Of course, assuming your Car
class has getters, you should replace c->c.make
with Car::getMake
, etc...
Map<String,Map<Integer,BigDecimal>> totals =
cars.stream ()
.collect (Collectors.groupingBy (Car::getMake,
Collectors.groupingBy (Car::getYear,
Collectors.reducing (new BigDecimal(0),
Car::getAmount,
BigDecimal::add))));
I ran this on your sample input and got:
{honda={2011=50000, 2012=50000}, ford={2012=12000}}
You can use groupingBy
with Map
and specify what to do with duplicate keys (ie add the amount
to generate aggregate result). Try the following:
List<Car> cars = new ArrayList<>(); //Your list
Map<String, Map<Integer, BigDecimal>> sum = cars.stream()
.collect(Collectors.groupingBy(c -> c.getMake(),
Collectors.toMap(c -> c.getYear(), c -> c.getAmount(),
(c1, c2) -> c1.add(c2))));
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.