有一个服务列表,例如:
List<Item> list = new ArrayList<>();
list.add(new Item(123456789, 01.04.2023));
list.add(new Item(123456789, 14.04.2023));
list.add(new Item(123456789, 21.04.2023));
list.add(new Item(123456789, 30.04.2023));
格式中的日期LocalDate,但为了清楚起见,这样表示。
有必要将服务列表分组,以便每个组在 14 天内都有服务。例如,对于上面的示例,将有两组:
第一个日期为 04/01/2023 和 04/14/2023 第二个日期为 04/21/2023 和 04/30/2023
我喜欢这样:
list.sort(Comparator.comparing(Item::getDate_in));
Map<Integer, List<Item>> groups = list.stream()
.collect(Collectors.groupingBy(i ->
(int) ChronoUnit.DAYS.between(list.get(0).getDate_in(), i.getDate_in()) / 14));
for (Map.Entry<Integer, List<Item>> entry1 : groups.entrySet()) {
System.out.println(entry1.getKey());
for (Item Item : entry1.getValue()) {
System.out.println(Item + " \n");
}
}
但结果是三个小组而不是两个。你能告诉我分组的最佳方法吗?
Map<Boolean, List<Item>>在问题https://ru.stackoverflow.com/questions/1507202/Separate-elements-by-conditions/1507257?noredirect=1#comment2704072_1507257中使用as是不合适的,因为此解决方案是将列表分为两组,并且可能会有三个小组。例如像这样:
List<Item> list = new ArrayList<>();
list.add(new Item(123456789, 01.04.2023));
list.add(new Item(123456789, 14.04.2023));
list.add(new Item(123456789, 15.04.2023));
list.add(new Item(123456789, 30.04.2023));
应该已经有三个组了。
看起来您是在动态计算组的开始时间而不是从第一个参考日期开始,这意味着您的最小日期值在您浏览列表时会发生变化,因此组数也会发生变化。
在这方面,
forEach不建议使用 Stream API / with a lambda 来构建这样的映射,因为这里需要记住流外的某个状态(参考日期),即要求 lambda 中的变量必须有效 final 被违反。但是,您可以简单地遍历按日期排序的输入列表并使用
computeIfAbsent. 列表第一个元素的日期作为初始关键日期。然后循环计算这个日期和当前元素的日期之间的天数差异,如果这个差异不满足指定条件(例如超过 14 天),则更新关键日期。实施示例:
测试:
对于这种情况,
Item(3, LocalDate.of(2023, 3, 20))将有两组:解决方案 c
forEach可以使用数组来编写(对数组本身的引用将是最终的),但这被认为是一个技巧:与流类似,-- 仅适用于顺序有序流,否则结果将不可预测:
如果日期和期间结束时间不重要,则可以使用以下公式作为分组参数
(номер_недели+1)/2。加 1 是必要的,这样第一周就不会成为“孤儿”。然后日期 1-2、3-4 等等将归为一组。该方法适用于一年内的日期。您还应该考虑过渡规则,当一月一日的周数可能在上一年的最后一周。