0

查询: 过滤下面的数据,在列表中查找每个月的最后一个日期。请注意,在这种情况下,数据中月份的最后一个日期可能与日历月的最后一个日期匹配,也可能不匹配。预期输出显示在第二个列表中。

研究:

  • 我相信TemporalAdjusters.lastDayOfMonth()在这种情况下不会有帮助,因为列表中的最后一个日期可能与日历月的最后一个日期匹配,也可能不匹配。
  • 我在 Stack Overflow 上检查了几个问题,也用 Google 搜索了,但我找不到与我需要类似的东西。

我希望这个问题很清楚,并为我指明了如何使用流来完成这一点,因为我不想使用for循环。

样本数据:

日期 模型 开始 结尾
27-11-1995 美国广播公司 241 621
27-11-1995 XYZ 3456 7878
28-11-1995 美国广播公司 242 624
28-11-1995 XYZ 3457 7879
29-11-1995 美国广播公司 243 627
29-11-1995 XYZ 3458 7880
1995 年 11 月 30 日 美国广播公司 244 630
1995 年 11 月 30 日 XYZ 3459 7881
01-12-1995 美国广播公司 245 633
01-12-1995 XYZ 3460 7882
04-12-1995 美国广播公司 246 636
04-12-1995 XYZ 3461 7883
27-12-1995 美国广播公司 247 639
27-12-1995 XYZ 3462 7884
28-12-1995 美国广播公司 248 642
28-12-1995 XYZ 3463 7885
29-12-1995 美国广播公司 249 645
29-12-1995 XYZ 3464 7886
01-01-1996 美国广播公司 250 648
01-01-1996 XYZ 3465 7887
02-01-1996 美国广播公司 251 651
02-01-1996 XYZ 3466 7888
29-01-1996 美国广播公司 252 654
29-01-1996 XYZ 3467 7889
30-01-1996 美国广播公司 253 657
30-01-1996 XYZ 3468 7890
31-01-1996 美国广播公司 254 660
31-01-1996 XYZ 3469 7891

截屏

需要输出:

日期 模型 开始 结尾
1995 年 11 月 30 日 美国广播公司 244 630
1995 年 11 月 30 日 XYZ 3459 7881
29-12-1995 美国广播公司 249 645
29-12-1995 XYZ 3464 7886
31-01-1996 美国广播公司 254 660
31-01-1996 XYZ 3469 7891

截屏

4

2 回答 2

2

好吧,两者的结合groupingBy可能maxBy会起作用。

我假设表的每条记录都是类型Event

record Event(LocalDate date, String model, int start, int end) { }

要获取表中该月的最后几天,我们可以使用groupingBy. 为了对其进行分组,我们可以首先创建一个分组类型。下面,我创建了一条EventGrouping记录1,其中包含static将 an 转换EventEventGrouping. 您所需的输出表明您希望按年-月-模型组合进行分组,因此我们只选择了这两个属性:

public record EventGrouping(YearMonth yearMonth, String model) {
        
    public static EventGrouping fromEvent(Event event) {
        return new EventGrouping(YearMonth.from(event.date()), event.model());
    }
}

然后,我们可以得到我们想要的结果,如下所示:

events.stream()
    .collect(Collectors.groupingBy(
        EventGrouping::fromEvent,
        Collectors.maxBy(Comparator.comparing(Event::date))
    ));

这里发生的是所有流元素都按我们的 分组EventGrouping,然后选择每个事件组的“最大值”。当然,最大值是该特定月份的最近日期。

请注意,对于组为空的情况,maxBy返回一个, 。Optional另请注意,结果Map是无序的。

collectingAndThen我们可以分别使用和地图工厂来解决这两个问题:

Map<EventGrouping, Event> map = events.stream()
    .collect(groupingBy(
        EventGrouping::fromEvent,
        () -> new TreeMap<>(Comparator.comparing(EventGrouping::yearMonth)
            .thenComparing(EventGrouping::model)),
        collectingAndThen(maxBy(Comparator.comparing(Event::date)), Optional::get)
    ));

注意:groupingBycollectingAndThen都是maxByjava.util.stream.Collectors.

  • 我们添加了Supplier一个TreeMap。ATreeMapMap由给定比较器具有可预测顺序的实现。这允许我们遍历按年-月-模型排序的结果条目。
  • collectingAndThen允许我们对给定的结果应用一个函数Collector。如前所述,maxBy返回一个Optional, 因为maxBy如果源流中没有元素则不适用。但是,在我们的案例中,这永远不会发生。所以我们可以安全地将 映射Optional到其包含的值。

1除了编写自定义类型,您还可以使用包含两个任意值的现有类,例如 a Map.Entry、 aPair甚至 a List<Object>

于 2022-01-02T15:19:42.843 回答
0

我建议创建一个Map<YearMonth, List<LocalDate>并解析您的所有日期并填写您的地图。之后,您对所有列表进行排序,每个列表中的最后一个(或第一个取决于排序顺序)值将是您想要的值

于 2022-01-02T10:25:31.637 回答