【问题标题】:Transform a map from daily data to weekly data in Java用 Java 将地图从每日数据转换为每周数据
【发布时间】:2018-10-04 07:46:22
【问题描述】:

我有一张LocalDate 和带有每日数据的整数的地图。现在我想用每周数据创建一个新地图,这意味着当我们将先前条目和当前条目下的整数相加时,新地图将包含累积计数。我陷入了困境。谁能帮我设计一个算法。我是 Java Stream api 的新手,如果可以使用 Stream API,它将

示例数据:

在图像中,我尝试遍历weeklyMap,然后在其中遍历dailyMap。但我不确定如何在代码(Java)中实现它。

编辑

代码sn-p:

Map.Entry<LocalDate, Integer> prevEntry = null;
        boolean firstTime = true;
        for (Map.Entry<LocalDate, Integer> currEntry : weeklyMap.entrySet()) {
            if (firstTime) {
                prevEntry = currEntry;
                firstTime = false;
                if (weeklyMap.containsKey(currEntry.getKey())) {
                    weeklyMap.put(currEntry.getKey(), currEntry.getValue());
                }
            } else {
                for (Map.Entry<LocalDate, Integer> todayEntry : dailyMap.entrySet()) {
                    if (prevEntry.getKey().equals(todayEntry.getKey())) {
                        prevEntry.setValue(todayEntry.getValue());
                    } else if(todayEntry.getKey().isAfter(prevEntry.getKey()) && todayEntry.getKey().isBefore(currEntry.getKey())) {
                        currEntry.setValue(currEntry.getValue() + todayEntry.getValue());
                    }
                }
            }
        }

【问题讨论】:

  • 边缘案例:一个月内有 31 天(> 4 周)会发生什么?是否有部分第 5 周,还是第 5 周结转到下月初?
  • @TimBiegeleisen 我不明白为什么要花几个月的时间?
  • @TimBiegeleisen 感谢您的评论,但我希望添加dailyMap 中的整数,这些整数属于weeklyMap 的日期
  • 所以你是说你当前的地图有几个星期的键,对吗?我从您的示例数据中得到了不同的印象。也许你应该包含代码。
  • 你真的应该包含你的代码;它会帮助你的问题。

标签: java algorithm java-stream treemap


【解决方案1】:

似乎最简单的方法是先构建一张累积总和的每日地图,然后只过滤掉星期一:

public static Map<LocalDate, Integer> cumulativeWeeklySum(SortedMap<LocalDate, Integer> data) {
    AtomicInteger cumulativeSum = new AtomicInteger(0);
    return data.entrySet().stream()
        .collect(Collectors.toMap(Map.Entry::getKey, e -> cumulativeSum.addAndGet(e.getValue())))
        .entrySet().stream()
        .filter(e -> e.getKey().getDayOfWeek() == DayOfWeek.MONDAY || e.getKey().equals(data.lastKey()))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

编辑:

如果要保留生成图的顺序,可以修改最后的collect()调用:

.collect(Collectors.toMap(
             Map.Entry::getKey, Map.Entry::getValue,
             (v1, v2) -> { throw new RuntimeException("Duplicate key - can't happen"); },
             TreeMap::new));

【讨论】:

  • 当我打印这张地图时,结果是这样的:{2018-10-15=22, 2018-10-08=12, 2018-10-22=27, 2018-10-01=2} 有没有办法让它像 TreeMap 一样有序?
  • 是的。但是我的dailyMap如何包含一个日期2018-10-23,它被这段代码忽略了。
  • 嗯,应该,不是吗? 2018-10-23 是星期二。
  • 不,不应该!我已经实现了无论最后一个日期是什么的逻辑,如果它没有包含在每周地图中,它将考虑最后一个日期。所以2018-10-22之后剩下的都需要总结一下,填入最后一个条目。
  • @FedericoPeraltaSchaffner 当然,谢谢。完毕。虽然这里不是真的需要(考虑到地图的构造方式,键是引用相等的),但它肯定是更好的样式。
【解决方案2】:

我认为您应该包括验证currentEntry.key == todayEntry.key 的边缘情况,然后总结以前的值。

代码可能看起来像这样:

if(todayEntry.getKey().equals(currEntry.getKey())) {
     currEntry.setValue(currEntry.getValue() + todayEntry.getValue() + prevEntry.getValue());
}

【讨论】:

  • 它就像一个魅力,但我已经接受了使用 Stream API 解决问题的答案,正如问题所说的那样。
猜你喜欢
  • 2020-07-06
  • 2021-04-28
  • 1970-01-01
  • 2013-05-02
  • 2020-06-13
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 2018-08-19
相关资源
最近更新 更多