java - 获取每周最大值 rom
问题描述
问题:
我有一个
Map<LocalDate, Integer>
并且我想LocalDate
使用 Java 8 Stream 按周对这些地图元素进行分组,并按周查找每个分组值的最大值。我目前遇到无法将密钥转换回流中的对象的问题,因为我没有在 Map
LocalDate
中创建对象所需的数据字段。LocalDate
如果我不将其转换为
LocalDate
并保留它String
,我不能使用TreeMap
键以自然顺序排列键值。如果我在对数据进行分组时不包括月份
DateTimeFormatter.ofPattern
,则两年之间的周数可能会重叠。如果我只使用周数整数作为流中地图的输出,则按周分组的值将与另一年的周数混合并重叠,即第 1 周的 2020-2021 年。
问题:
- 如何使用 java 流获得每周值的最大值?
数据集:
Map<LocalDate,Integer> CumulativeGarbageWasteDate = new HashMap<LocalDate,Integer>();
CumulativeGarbageWasteDate.put(LocalDate.parse(("5/2/2020"),DateTimeFormatter.ofPattern("[M/d/yyyy][M/d/yy]")),2400);
CumulativeGarbageWasteDate.put(LocalDate.parse(("12/24/20"),DateTimeFormatter.ofPattern("M/d/yy")),140);
CumulativeGarbageWasteDate.put(LocalDate.parse(("5/2/20"),DateTimeFormatter.ofPattern("M/d/yy")),2400);
CumulativeGarbageWasteDate.put(LocalDate.parse(("01/1/21"),DateTimeFormatter.ofPattern("M/d/yy")),182);
CumulativeGarbageWasteDate.put(LocalDate.parse(("01/2/21"),DateTimeFormatter.ofPattern("M/d/yy")),203);
CumulativeGarbageWasteDate.put(LocalDate.parse(("01/3/21"),DateTimeFormatter.ofPattern("M/d/yy")),321);
CumulativeGarbageWasteDate.put(LocalDate.parse(("01/3/21"),DateTimeFormatter.ofPattern("M/d/yy")),421);
CumulativeGarbageWasteDate.put(LocalDate.parse(("5/2/2021"),DateTimeFormatter.ofPattern("[M/d/yyyy][M/d/yy]")),2400);
CumulativeGarbageWasteDate.put(LocalDate.parse(("01/6/21"),DateTimeFormatter.ofPattern("M/d/yy")),1200);
CumulativeGarbageWasteDate.put(LocalDate.parse(("01/31/21"),DateTimeFormatter.ofPattern("M/d/yy")),2400);
代码:
private static Map<LocalDate, Integer> sumByWeek (Map<LocalDate,Integer> CumulativeGarbageWasteDate){
DateTimeFormatter formatter3 = new DateTimeFormatterBuilder().appendPattern("w/M/YY").parseDefaulting(ChronoField.DAY_OF_WEEK,DayOfWeek.FRIDAY.getValue()).toFormatter();
return CumulativeGarbageWasteDate
.entrySet()
.stream()
.collect(Collectors.groupingBy(
row-> LocalDate.parse(row.getKey().format(DateTimeFormatter.ofPattern("w/M/YY")),formatter3),
TreeMap::new,
Collectors.reducing(0, x->x.getValue(),Math::max)));
}
错误:
这是我在运行代码时遇到的错误。
java.time.format.DateTimeParseException: Text '5/2/20' could not be parsed: Conflict found: Field MonthOfYear 1 differs from MonthOfYear 2 derived from 2020-01-31
解决方案
输出映射的类型为Map<LocalDate, Integer>
,其中键是该周具有最高值的日期。(我正在拆分解决方案以使其更易于理解)。
首先,我建议创建一个类(可能是一个内部类)来保存日期及其对应的值。这将使处理变得容易。
private static class MyData {
private LocalDate date;
private int value;
// getters and a constructor
}
注意:假设在下面的代码中,像, , ,这样的Collectors
方法是静态导入的。grouping
toMap
toList
mapping
可以使用WeekFields
.(参考)检索一年中的一周
注意: row.getKey().getYear()
不应在下面的代码中使用而不是row.getKey().get(weekFields.weekBasedYear())
用于获取年份,因为它可能会在以下情况下产生不正确的结果:
2022-01-01
and 2021-12-31
,属于 2022 年的第 1 周。因此,如果我们使用getYear()
,则相应生成的字符串将为1/2022
and 1/2021
,这是不正确的。在这种情况下,预期的字符串是1/2022
.
WeekFields weekFields = WeekFields.of(Locale.getDefault());
// function to generate a key of the form: week~year. year included to avoid overlap
Function<Entry<LocalDate, Integer>, String> groupFn
= row -> String.format("%d/%d",
row.getKey().get(weekFields.weekOfWeekBasedYear()),
row.getKey().get(weekFields.weekBasedYear()));
现在将输入转换为MyData
对象:
Map<String, List<MyData>> temp =
input.entrySet()
.stream()
.collect(groupingBy(groupFn,
TreeMap::new,
mapping(e -> new MyData(e.getKey(), e.getValue()), toList())));
现在我们在一周内找到最大值的日期:
Function<Entry<String, List<MyData>>, MyData> maxDataFn
= entry -> entry.getValue()
.stream()
.collect(collectingAndThen(maxBy(Comparator.comparingInt(MyData::getValue)),
Optional::get));
TreeMap<LocalDate, Integer> result
= temp.entrySet()
.stream()
.map(maxDataFn)
.collect(toMap(MyData::getDate, MyData::getValue, Integer::max, TreeMap::new));
推荐阅读
- python - 熊猫 read_csv 跳到新行
- spring - 测试期间出现 UnsatisfiedDependencyException
- netsuite - Netsuite-Suitelet post to restlet 获取参数
- ios - 无法在 Xcode 10 中查找屏幕比例和意外的物理屏幕方向
- php - Laravel如何将参数传递给中间件?
- spring - 杰克逊将日期序列化为时间戳
- javascript - 重新加载移动页面脚本响应
- mysql - 每分钟 SQL 的插入量
- c# - 将多个具有 DataRelations 的 DataTable 连接到一个新的 DataTable 中
- python - 使用 Anaconda installe 在 Windows 上获取 CUDA 和 CUDNN 版本