流收集操作可以成为特定的POJO而不是Map吗?

时间:2019-05-08 16:53:20

标签: java java-8 java-stream

我想对多个字段进行分组,并产生和输出一个POJO。

原始POJO是这样的:

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class DealDTO {
    @EqualsAndHashCode.Include
    private String id;

    private Float amount;
    private Date closeDate;
    private String stage;

    public int getYear() {
        return getLocalDate().getYear();
    }

    public int getMonth() {
        return getLocalDate().getMonthValue();
    }

    private LocalDate getLocalDate() {
        return getCloseDate().toInstant()
            .atZone(ZoneId.systemDefault()).toLocalDate();
    }
}

目标POJO

@Data
public class GroupByYearMonthStageDTO {
    private int year;
    private int month;
    private String stage;
    private DoubleSummaryStatistics statistics;
}

下面的代码产生了预期的分组:

List<DealDTO> list;
var grouping = list.stream().collect(
  groupingBy(DealDTO::getYear,
    groupingBy(DealDTO::getMonth,
      groupingBy(DealDTO::getStage, summarizingDouble(DealDTO::getAmount)))));

但是.....分组的类型是:

Map<Integer, Map<Integer, Map<String, DoubleSummaryStatistics>>> 

我想看看收集操作中是否有办法将输出更改为最终分组类型为

List<GroupByYearMonthStageDTO>

2 个答案:

答案 0 :(得分:1)

作为groupingBy的第一个参数,发送创建目标POJO的lambda,并使用summarizingDouble收集器作为第二个参数。之后,您必须遍历结果图并设置统计信息

Map<GroupByYearMonthStageDTO, DoubleSummaryStatistics> collect = list.stream()
            .collect(groupingBy(d -> new GroupByYearMonthStageDTO(d.getYear(), d.getMonth(), d.getStage()),
                            summarizingDouble(DealDTO::getAmount)));

collect.forEach(GroupByYearMonthStageDTO::setStatistics);
Set<GroupByYearMonthStageDTO> groupByYearMonthStageDTOS = collect.keySet();

答案 1 :(得分:0)

在不知道Target POJO是什么样的情况下,我真的无法为您实现 ,但是您需要的是自定义Collector实现。完成分组后,可以将分组数据传递到Collector,并且必须将其从分组数据中减少到POJO中。

请注意,甚至可能希望跳过分组,而由您的Collector处理。

有用的链接:

Java Collector

groupingBy()

Java 8 grouping using custom collector