[英]Calculating Min and Max sums from a List of Integer using Java 8 streams
[英]How to get weekly max value from Map<LocalDate,Integer> using streams
问题:
我有一个Map<LocalDate, Integer>
并且我想使用LocalDate
按周对这些地图元素进行分组,并使用 Java 8 Stream 按周查找每个分组值的最大值。
我目前有在那里我可以不是关键放回转换问题LocalDate
流中的对象,由于这样的事实,我没有必要的数据字段创建的对象LocalDate
入地图。
如果我不将其转换为LocalDate
并将其保留为String
,则无法使用TreeMap
使用键以自然顺序排列键值。
如果我在对数据进行分组时不将月份包含在DateTimeFormatter.ofPattern
,那么两年之间的周数可能会重叠。
如果我只使用周数整数作为流中地图的输出,则按周分组的值将与另一年的周数混合并重叠,即 2020-2021 与第 1 周。
题:
如何使用java流获得每周值的最大值?
如何将密钥字符串格式化为LocalDate
并且仅将数周、数月LocalDate
年作为流的输出?
数据集:
这是地图中实际数据的一小部分。 的实际日期输入到地图具有介于2020-01-15
到2021-08-16
和它们一起在地图其不是唯一的各累积整数唯一的。
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
尝试:
我已经尝试使用这些代码行来替换上面的行代码行,可惜它不起作用或者它不是我需要的对象类型。
row-> (row.getKey().format(DateTimeFormatter.ofPattern("w/M/YY"))),
row-> LocalDate.parse(row.getKey().format(DateTimeFormatter.ofPattern("w/M/YY")),formatter),
预期输出:
以下是打印地图时的预期输出:[年/月/年的周数=分组周值中的最高值]
{50/12/19=140,1/1/20=421,2/1/20=1200}
输出地图的类型为Map<LocalDate, Integer>
,其中键是该周具有最高值的日期。 (我正在拆分解决方案以使其更易于理解)。
首先,我建议创建一个类(可能是一个内部类)来保存日期及其相应的值。 这将使处理变得容易。
private static class MyData {
private LocalDate date;
private int value;
// getters and a constructor
}
注意:假设在下面的代码中为Collectors
方法(如grouping
、 toMap
、 toList
、 mapping
进行静态导入。
可以使用WeekFields
检索一年中的第WeekFields
。(请参阅)
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().getYear());
现在将输入转换为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));
将appendPattern("w/M/YY")
更改为appendPattern("dd/MM/yyy)
并将ofPattern("w/M/YY")
更改为ofPattern(dd/MM/yyyy")
。
使用 LocalDate 的parse()
方法。 LocalTime 类的parse()
方法用于从作为参数传递的字符串(例如2002-02-21
获取 LocalTime 的实例。该字符串必须具有有效的日期时间并使用DateTimeFormatter.ISO_LOCAL_DATE
进行解析。 使用DateTimeFormatter
正确格式化日期字符串。
下面是例子
import java.time.format.DateTimeFormatter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
public class MyClass {
public static void main(String args[]) {
Map<LocalDate, Double> map = new HashMap<>();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate date1 = LocalDate.parse("2002/02/21", df);
LocalDate date2 = LocalDate.parse("2003/02/21", df);
map.put(date1, 12.4);
map.put(date2, 14.4);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.