Я только помогу вам исправить первый, вы можете понять это и исправить второй тоже (это почти то же самое).
Вы сначала говорите:
Stream.iterate(LocalDate.of(yearSince, 0, 0), date -> date.plusYears(1))
Но вам действительно нужно повторять лет здесь? Вам нужно выяснить Mondays
(что такое дни, нет?). В этом главная проблема, так как ваше "l oop" произойдет только столько раз, сколько эта разница в годах. Допустим, вы хотите 2018-2020
интервал - сколько раз вы собираетесь повторять то, что у вас есть сейчас?
Но теперь вам нужно подумать, когда «остановить» это l oop - и вот почему вы использовали limit
:
.limit(yearUntilInclusive)
Проблема в том, что если вы правильно итерируете days
, вы не знаете, когда остановиться, не так ли? В идеале вы хотите остановиться, используя Predicate
, например: я хочу начать с первого day
из 2018
и остановиться на последнем day
из 2020
. limit
на самом деле не может этого сделать (вы можете через разницу дней от этого last
до этого first
- я дам вам понять, как). Или мне проще использовать Predicate
с takeWhile
(требуется не менее 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
)
);