Java集合缩减为Map

时间:2017-08-02 20:30:12

标签: java java-8 java-stream

我有一个Map个对象列表,如下所示:

year  => 2016,
month => 10,
day   => 11,
count => 123

我在startDate<范围内每天都有一个元素。 endDate

我希望能够根据startDateendDate之间的时间间隔将这些元素缩减为不同的时间分组。如果startDateendDate之间的差异大于4年,我想将它们分组为数年。如果差异小于四年,但大于一年,我想将它们分成几个月。如果它不到一年,但超过一个月,我想分成几周。不到一个月的任何事情,没有必要的分组。

当我说“群组”时,我的意思是我想总结属于特定年份的所有内容的count元素(使用上面的第一个示例),并返回单个每年的地图如下所示:

year   => 2016,
month  => 1
day    => 1
count  => 9897

我知道必须有一种优雅的方法来实现这一目标,但我很难将我的大脑包裹在逻辑之中。

2 个答案:

答案 0 :(得分:2)

我不明白,你可以这样做:

if(starDate is smaller then endDate by 4 year) {

              resultMap = yourList.stream()
                      .collect(Collectors.groupingBy(map.get("year"),
                           Collectors.summingInt(map.get("count")));

}

else if(starDate is... another condition) {
      resultMap = yourList.stream()
                      .collect(Collectors.groupingBy(map.get("month"),
                           Collectors.summingInt(map.get("count")));

}

// all the there cases...

稍后将此结果映射到您想要的任何内容。

答案 1 :(得分:2)

像往常一样使用Collectors.groupingBy并提供您想要的分类器。

final LocalDate endDate = dateCounts.last().getDate();
Function<DateCount, LocalDate> mapLocalDate = dc-> {
    LocalDate ld = dc.getDate();
    long m = Period.between(ld, endDate ).toTotalMonths();
    if ( m > 4*12 ) {
        return ld.withMonth(1).withDayOfMonth(1);
    } else if ( m >= 1 ) {
        return ld.withDayOfMonth(1);
    } else {
        return ld;
    }
};
Map<LocalDate, Long> r = dateCounts.stream()
.collect(Collectors.groupingBy(
        mapLocalDate, 
        TreeMap::new, 
        Collectors.summingLong(DateCount::getCount)
    )
);
System.out.println(  "EndDate = " + endDate );
System.out.println(  r );