gpt4 book ai didi

java - 使用 java Stream API 对日期进行排序、分组和计数

转载 作者:行者123 更新时间:2023-12-04 10:34:31 25 4
gpt4 key购买 nike

如何使用 Stream API 解决以下示例。

/*
* Calculate the total number of Mondays for the specified years grouped by month
*/
EnumMap<Month, Long> totalMondaysByMonth(int yearSince, int yearUntilInclusive);

/*
* Issue a list of Fridays on the 13th for the specified years,
* sorted in ascending order first by year, and second by name of the month
*/
List<LocalDate> friday13s(int yearFrom, int yearUntilInclusive);

我的示例解决方案:
public EnumMap<Month, Long> totalMondaysByMonth(int yearSince, int yearUntilInclusive) {
return Stream.iterate(LocalDate.of(yearSince, 0, 0), date -> date.plusYears(1))
.limit(yearUntilInclusive)
.filter(x -> x.getDayOfWeek() == DayOfWeek.MONDAY)
.collect(Collectors.groupingBy(LocalDate::getMonth, Collectors.summingLong(???));

}

我应该在 (Collectors.summingLong(???))) 中插入什么代码来计算星期一的数量?
public List<LocalDate> friday13s(int yearFrom, int yearUntilInclusive) {
return Stream.iterate(LocalDate.of(yearFrom, 0, 0), date -> date.plusYears(1))
.limit(yearUntilInclusive)
.filter(x -> x.getDayOfWeek() == DayOfWeek.FRIDAY || x.getDayOfMonth() == 13)
.sorted(Comparator.comparing(LocalDate::getYear).thenComparing(LocalDate::getMonth))
.collect(Collectors.toList());
}

告诉我如何正确写作。

最佳答案

我只会帮你修复第一个,你可以理解这一点并修复你的第二个(几乎相同)。

你先说:

Stream.iterate(LocalDate.of(yearSince, 0, 0), date -> date.plusYears(1))

但是你真的需要在这里迭代几年吗?您需要找出 Mondays (是几天,不是吗?)这是这里的主要问题,因为您的“循环”只会发生与年差一样多的次数。假设您想要 2018-2020间隔 - 你打算用你现在拥有的东西迭代多少次?

但是现在你需要考虑什么时候“停止”这个循环——这就是你使用 limit 的原因。 :
 .limit(yearUntilInclusive)

问题是,如果您正确地迭代 days ,你真的不知道什么时候停止,是吗?理想情况下,您希望停止使用 Predicate ,如:我想从第一个 day 开始的 2018并停在最后 day2020 . limit不能真正做到这一点(你可以通过从 last 到那个 first 的天数差异 - 我会让你弄清楚如何)。或者,我发现更容易使用 PredicatetakeWhile (至少需要 java-9)。

然后是 Collectors.summingLong可以做成 Collectors.summingInt (您需要很多年才能从 32 位整数跳转到 64 位长)。你需要在那里做什么?对于匹配的每一天,只需添加一个。简单地“加一个”也称为 counting并且有一个收集器 Collectors.counting()你也可以使用。

最后一点是 EnumMap可以拿 Map作为其构造函数的参数;像这样:
public static EnumMap<Month, Integer> totalMondaysByMonth(int yearSince, int yearUntilInclusive) {

return Stream.iterate(LocalDate.of(yearSince, 1, 1), date -> date.plusDays(1))
.takeWhile(date -> date.getYear() <= yearUntilInclusive)
.filter(x -> x.getDayOfWeek() == DayOfWeek.MONDAY)
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(LocalDate::getMonth, Collectors.summingInt(x -> 1)),
EnumMap::new
)
);
}

但是你能在这里更有效吗?你可以找到你开始的那一年的第一个星期一,然后从那开始迭代几周,而不是几天:
 LocalDate firstMonday = LocalDate.of(yearSince, 1, 1).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
EnumMap<Month, Integer> right =
Stream.iterate(firstMonday, date -> date.plusWeeks(1))
.takeWhile(date -> date.getYear() <= yearUntilInclusive)
.collect(
Collectors.collectingAndThen(
Collectors.groupingBy(LocalDate::getMonth, Collectors.summingInt(x -> 1)),
EnumMap::new
)
);

关于java - 使用 java Stream API 对日期进行排序、分组和计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60253485/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com