3

我有自己的类CheckIn,其属性day为 as StringworkingHoursasintinProgressas boolean

public class CheckIn {
    public int id;
    public String day;
    public int workingHours;
    public boolean inProgress;

    public CheckIn(String day, in hours, boolean inProgress) {
        this.day = day;
        this.workingHours = hours;
        this.inProgress = inProgress;
    }
}

我的系统中有条目列表,我需要这些条目的摘要并将它们与天分组并总结工作时间。在这里没问题,我可以使用 lambda 来实现,但是如果条目中的任何内容为真,那么我想将进度设置为真怎么办?

// Suppose this is the inputs 
List<CheckIn> checkinsList = new ArrayList<>();
checkinsList.add(new CheckIn("26-11-2015",6,true));
checkinsList.add(new CheckIn("27-11-2015",6,false));
checkinsList.add(new CheckIn("26-11-2015",6,false));
checkinsList.add(new CheckIn("27-11-2015",4,false));
checkinsList.add(new CheckIn("26-11-2015",1,false));
checkinsList.add(new CheckIn("28-11-2015",6,false));
checkinsList.add(new CheckIn("28-11-2015",6,false));
checkinsList.add(new CheckIn("28-11-2015",6,true));


List<CheckIn> summary = new ArrayList<>();

checkinsList.stream().collect(Collectors.groupingBy(Function.identity(),
    () -> new TreeMap<>(
        Comparator.<CheckIn, String>comparing(entry -> entry.day)),
        Collectors.summingInt(entry -> entry.duration))).forEach((e, sumTargetDuration) -> {
        CheckIn entry = new CheckIn();
        entry.day = e.day;
        entry.duration = sumTargetDuration;
        // Here my something like what I need?
        entry.inProgress = e.inProgress;
        summary.add(entry);
});

我需要summary列表包含(在这种情况下用于输入)在这 3 天内有 3 个项目:

我想要这样的结果:

  • 第一项"26-11-2015" , 13 , true<--true因为“2015 年 26 月 11 日”有 1 项为真。
  • 第二项"27-11-2015" , 10 , false
  • 第三项"28-11-2015" , 18 , true

inProgress如果那天有任何条目,我希望摘要为真,inProgress == true它是否适用于 lambda?

4

1 回答 1

3

您需要为此任务构建自定义收集器。问题是没有内置的收集器可以将多个收集器组合在一起并应用整理操作。在这种情况下,我们需要组合 3 个收集器:summingIntreducingor每个 sinProgressmapping,映射到日期。

以下类将在收集过程中保存摘要并相应地计算结果。我们可以添加关于这一天的额外检查,因为它在整个过程中应该是相同的,但为了简单起见,我将它们省略了。

public class CheckInSummary {

    private int workingHours;
    private boolean inProgress;
    private String day;

    public void accept(CheckIn checkIn) {
        workingHours += checkIn.workingHours;
        inProgress = inProgress || checkIn.inProgress;
        day = checkIn.day;
    }

    public CheckInSummary combine(CheckInSummary summary) {
        workingHours += summary.workingHours;
        inProgress = inProgress || summary.inProgress;
        return this;
    }

    public CheckIn finish() {
        return new CheckIn(day, workingHours, inProgress);
    }

}

然后,您可以使用以下方法从此类创建收集器:

private static Collector<CheckIn, ?, CheckIn> summary() {
    return Collector.of(
                CheckInSummary::new,
                CheckInSummary::accept,
                CheckInSummary::combine,
                CheckInSummary::finish
           );
}

你终于可以像这样使用它了:

List<CheckIn> result = 
      new ArrayList<>(checkinsList.stream()
                                  .collect(groupingBy(c -> c.day, summary()))
                                  .values());

测试用例的输出:

[[27-11-2015, 10, false], [26-11-2015, 13, true], [28-11-2015, 18, true]]

此列表未排序,但如果您想对其进行排序,您只需要额外调用来sort()比较日期。

于 2015-11-26T16:15:26.590 回答