gpt4 book ai didi

java - 使用 startDate 和 endDate 按月分组

转载 作者:行者123 更新时间:2023-12-02 09:14:54 24 4
gpt4 key购买 nike

我有一个类模块,其中包含

private LocalDate startDate;        
private LocalDate endDate;
private Map<Teacher, Integer> workedHoursPerDay;

每个老师都有一个属性

private int hourlyWage;   

请求是获取按月分组的所有教师的每月预算。预期返回的是Map。我进行了搜索,但我不知道如何使用 startDate 和 endDate 来做到这一点。

单个模块的每月支出是分配给该模块的所有教师在该月所有工作日内的累计成本。

逻辑是:-从所有模块中获取(Set)教授该模块的老师和小时数(MapworkingHoursPerDay)。然后将每位教师的工作时间乘以小时工资。最后,使用每个模块的 startDate 和 endDate 按月对成本进行分组。

我已经做了类似的事情,但没有得到预期的结果

公共(public) map calculateCumulativeMonthlySpends() {

    //Get the min startDate of all the  modules
LocalDate localDateStart = modules.stream()
.flatMap(modules -> module.getWorkingDays().stream())
.min(LocalDate::compareTo).get();
//Get the max endDate of all the modules
LocalDate localDateEnd = modules.stream()
.flatMap(module -> module.getWorkingDays().stream())
.max(LocalDate::compareTo).get();

//Iterate from the start date to the end date, calculate the daily cost for all the module
//and sum the cost of all the days for the all modules
//Then create a map with moth as a key and the cost of all the modules for each month
//Finally sort the map by key

return Stream.iterate(localDateStart, d -> d.plusDays(1))
.limit(ChronoUnit.DAYS.between(localDateStart, localDateEnd) + 1)
.collect(Collectors.toMap(LocalDate::getMonth, day -> dailyCost(day, modules), Integer::sum))
.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
}

/**
* Calculate the daily cost for all the modules
* Check if the modules's working days contain the attribute day
* If yes sum(), add the daily cost of this module to the other modules' daily cost
*
* @param day
* @param modules
* @return
*/
private Integer dailyCost(LocalDate day, Set<Module> modules) {

return modules.stream()
.filter(module -> module.getWorkingDays().contains(day))
.flatMap(p -> p.getCommittedHoursPerDay().entrySet().stream())
.mapToInt(e -> e.getKey().getHourlyWage() * e.getValue())
.sum();
}

代码已修改。我现在已经得到了预期的结果,但我希望有更好的方法来做到这一点。

预计:{1月=19529、2月=26909、3月=35593、4月=60243、5月=79172、6月=70135、7月=72470、8月=40161、9月=21750、10月=8636、十一月=1344}

最佳答案

如果没有更多信息,很难找到代码中的错误。但解释一下如何自己找到它可能会对您更有帮助。

dailyCost 中的单个表达式太复杂,无法调试。 Java 流非常棒,但它们有一个非常大的问题:使用交互式调试器调试它们非常困难(请参阅 Problems using interactive debuggers with Java 8 streams 不幸的是没有有用的答案)。

秘诀是让你的运算符(operator)链简短而明显。在可能的情况下分成代表单一职责并且可以单独进行单元测试的单独方法。然后您就可以放心地将这些方法构建到您的解决方案中。

例如:

.filter(p -> (p.getStartDate().isBefore( day)  || p.getStartDate().equals(day)))
.filter(p -> p.getEndDate().isAfter(day) || p.getEndDate().equals(day))

可能成为:

.filter(p -> p.wasActiveOnDay(day))

还有:

.mapToInt(p -> p.getCommittedHoursPerDay().entrySet().stream()
.mapToInt(e -> e.getKey().getHourlyWage() * e.getValue()).sum())

可能成为:

.mapToInt(Module:getTotalWages)

其中每一个都可以作为模块测试的一部分进行单元测试。这会给你留下:

return modules.stream()
.filter(m -> m.wasActiveOnDay(day))
.mapToInt(Module::getTotalWages).sum();

该语句更容易调试。

关于java - 使用 startDate 和 endDate 按月分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59079848/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com