如何使用带有地图和列表的Java 8 Streams计算两个子组的总数

Ste*_*ier 2 java java-8 java-stream

我有一个CarPOJO:

class Car
{
  String make;
  int year;
  BigDecimal amount;
}
Run Code Online (Sandbox Code Playgroud)

和那样List<Car>的汽车:

make  : year : price
honda : 2011 : $20,000
honda : 2011 : $30,000
honda : 2012 : $50,000
ford  : 2012 : $12,000
Run Code Online (Sandbox Code Playgroud)

结果我想要的地方:

// Map<make, List<year, totalForYear>>
Map<String, Map<int, BigDecimal>> revenuesByMakeAndYear;
Run Code Online (Sandbox Code Playgroud)

如何使用Streams实现这一目标?到目前为止,我已经到了一半:

// 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())));
Run Code Online (Sandbox Code Playgroud)

但是我该如何进入下一步呢?

Era*_*ran 5

您可以使用嵌套groupingBy按make和year分组,然后reducing生成总收入):

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))));
Run Code Online (Sandbox Code Playgroud)

如果要总结的财产是不是BigDecimal,你可能已经取代了reducing用简单summingIntsummingLongsummingDouble.

当然,假设你的Car班级有吸气剂,你应该c->c.makeCar::getMake等等替换......

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))));
Run Code Online (Sandbox Code Playgroud)

我在你的样本输入上运行了这个并获得:

{honda={2011=50000, 2012=50000}, ford={2012=12000}}
Run Code Online (Sandbox Code Playgroud)