java - Java 8 api 流。需要解决重复密钥问题
问题描述
我有一个如下所示的日志文件:
LSR2019-07-12_12:07:21.554
KMH2019-07-12_12:09:44.291
RGH2019-07-12_12:29:28.352
RGH2019-07-12_12:33:08.603
我有一个解析器将数据解析为缩写/日期/时间:
public Map <String, ?> parse() throws IOException {
try (Stream<String>lines = Files.lines(path)){
return lines.collect(Collectors.toMap(
string -> string.substring(0,3),
string -> new DateAndTimeInfo(LocalTime.from(DateTimeFormatter.ofPattern("HH:mm:ss.SSS").parse((string.substring(3).split("_")[1]))),
LocalDate.parse(string.substring(3).split("_")[0], DateTimeFormatter.ofPattern("yyyy-MM-dd"))),
(string1, string2)-> ??? )); //Struggle here
解析后,它会创建一个映射,其中包含作为键的缩写和 DateAndTimeInfo 类的实例。该类如下所示:
public class DateAndTimeInfo {
private List<LocalTime> localTime;
private List<LocalDate> localDate;
public DateAndTimeInfo(LocalTime localTime, LocalDate localDate) {
this.localTime = Arrays.asList(localTime);
this.localDate = Arrays.asList(localDate);
}
public List<LocalTime> getLocalTime() {
return this.localTime;
}
public List<LocalDate> getLocalDate() {
return this.localDate;
}
public void addAnotherLapTime(LocalTime localtime, LocalDate localDate) {
this.localTime.add(localtime);
this.localDate.add(localDate);
}
}
一切正常,直到日志文件有重复的缩写。一旦出现重复键,我希望将数据存储在 DateAndTimeInfo 对象中,该对象是在解析第一个重复项时创建的。为此,我有addAnotherLapTime()
方法。问题是我不知道如何在我的流中写它。
解决方案
由于值的组合最终会出现在List
对象中,因此这是groupingBy
收集器的任务。
但首先,你必须修复DateAndTimeInfo
类。它只是构造函数
public DateAndTimeInfo(LocalTime localTime, LocalDate localDate) {
this.localTime = Arrays.asList(localTime);
this.localDate = Arrays.asList(localDate);
}
创建固定大小的列表,因此该方法
public void addAnotherLapTime(LocalTime localtime, LocalDate localDate) {
this.localTime.add(localtime);
this.localDate.add(localDate);
}
将失败并出现异常。
当你使用
public class DateAndTimeInfo {
private List<LocalTime> localTime;
private List<LocalDate> localDate;
public DateAndTimeInfo() {
localTime = new ArrayList<>();
localDate = new ArrayList<>();
}
public List<LocalTime> getLocalTime() {
return this.localTime;
}
public List<LocalDate> getLocalDate() {
return this.localDate;
}
public void addAnotherLapTime(LocalTime localtime, LocalDate localDate) {
this.localTime.add(localtime);
this.localDate.add(localDate);
}
}
相反,您可以像收集地图一样
public Map<String, DateAndTimeInfo> parse() throws IOException {
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH:mm:ss.SSS");
try(Stream<String>lines = Files.lines(path)){
return lines.collect(Collectors.groupingBy(
string -> string.substring(0,3),
Collector.of(DateAndTimeInfo::new, (info,str) -> {
LocalDateTime ldt = LocalDateTime.parse(str.substring(3), f);
info.addAnotherLapTime(ldt.toLocalTime(), ldt.toLocalDate());
}, (info1,info2) -> {
info1.getLocalDate().addAll(info2.getLocalDate());
info1.getLocalTime().addAll(info2.getLocalTime());
return info1;
})));
}
}
groupingBy
允许为组指定一个收集器,此解决方案Collector
为DateAndTimeInfo
对象创建一个新的 ad-hoc。
您可以考虑是否真的要将日期和时间保留在不同的列表中。
替代方案是:
public class DateAndTimeInfo {
private List<LocalDateTime> localDateTimes;
public DateAndTimeInfo(List<LocalDateTime> list) {
localDateTimes = list;
}
public List<LocalDateTime> getLocalDateTimes() {
return localDateTimes;
}
// in case this is really needed
public List<LocalTime> getLocalTime() {
return localDateTimes.stream()
.map(LocalDateTime::toLocalTime)
.collect(Collectors.toList());
}
public List<LocalDate> getLocalDate() {
return localDateTimes.stream()
.map(LocalDateTime::toLocalDate)
.collect(Collectors.toList());
}
}
接着
public Map<String, DateAndTimeInfo> parse() throws IOException {
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH:mm:ss.SSS");
try(Stream<String>lines = Files.lines(path)){
return lines.collect(Collectors.groupingBy(
string -> string.substring(0,3),
Collectors.collectingAndThen(
Collectors.mapping(s -> LocalDateTime.parse(s.substring(3), f),
Collectors.toList()),
DateAndTimeInfo::new)));
}
}
推荐阅读
- azcopy - 验证 azcopy 或 az storage cli 以上传到 Azurite docker 模拟器
- python - 如何在 Windows 上为 python 2.7 32bit 安装 PIL?
- python - 在 Pandas Python 中对数据帧进行排序和过滤
- node.js - webpack-dev-server 的 npm install 谁需要'-g'?
- express - TypeError:bodyParser.json 不是 nuxt.js 中的函数
- node.js - 等到上一个查询完成后再运行下一个查询
- barcode - 将条码创建为“Alt+Tab”并切换 windows 应用程序,然后 Enter 键
- apache-spark - 转换用“|”分隔的表头和列数据 到 pyspark 中具有特定标题名称和数据行的单独列
- python - 如何自动抓取然后发出警报?
- c# - C# 应用程序故障排除