首页 > 解决方案 > 获取每周最大值 rom

问题描述

问题:

问题:

数据集:

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

标签: javajava-8java-stream

解决方案


输出映射的类型为Map<LocalDate, Integer>,其中键是该周具有最高值的日期。(我正在拆分解决方案以使其更易于理解)。

首先,我建议创建一个类(可能是一个内部类)来保存日期及其对应的值。这将使处理变得容易。

private static class MyData {
    private LocalDate date;
    private int value;
    
    // getters and a constructor
}

注意:假设在下面的代码中,像, , ,这样的Collectors方法是静态导入的。groupingtoMaptoListmapping


可以使用WeekFields.(参考)检索一年中的一周

注意: row.getKey().getYear()不应在下面的代码中使用而不是row.getKey().get(weekFields.weekBasedYear())用于获取年份,因为它可能会在以下情况下产生不正确的结果: 2022-01-01and 2021-12-31,属于 2022 年的第 1 周。因此,如果我们使用getYear(),则相应生成的字符串将为1/2022and 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));


推荐阅读