【问题标题】:Filter and map a java stream at the same time同时过滤和映射一个java流
【发布时间】:2016-08-22 05:38:30
【问题描述】:
我有一个字符串列表,每个字符串代表一个日期。我想将此列表映射到 DateTime 对象列表中;但是,如果任何字符串无效(引发异常),我想记录一个错误但不将其添加到最终列表中。有没有办法同时进行过滤和映射?
这是我目前拥有的:
List<String> dateStrs = ...;
dateStrs.stream().filter(s -> {
try {
dateTimeFormatter.parseDateTime(s);
return true;
} catch (Exception e) {
log.error("Illegal format");
return false;
}
}.map(s -> {
return dateTimeFormatter.parseDateTime(s);
}.collect(...);
有什么办法可以让我不必为每个元素解析两次日期时间?
谢谢
【问题讨论】:
标签:
java
datetime
dictionary
filter
java-stream
【解决方案1】:
您可以首先将字符串映射到其解析日期。如果遇到无效的日期字符串,则记录它并返回 null。
然后在第二步中过滤非空日期。
【解决方案2】:
以相反的顺序进行操作。
List<String> dateStrs = ...;
dateStrs.stream().map(s -> {
try {
return dateTimeFormatter.parseDateTime(s);
} catch (Exception e) {
return null;
}
}).filter(d -> d != null).collect(...);
(我意识到这与@wero 本质上相同,但为时已晚,但希望代码能够清楚地说明。)
【解决方案3】:
在我看来,在这里使用flatMap 会更符合习惯用法:
dateStrs.stream().flatMap(s -> {
try {
return Stream.of(dateTimeFormatter.parseDateTime(s));
} catch (Exception e) {
return Stream.empty();
}
}).collect(...);
在这里您可以一次操作完成所有操作。
【解决方案4】:
Java 9 更新
与 Tagir 的解决方案类似,您可以映射到 Optional,在转换无法产生值时记录错误。然后,使用新的Optional::stream 方法,您可以在可选上flatMap,从流中删除失败的转换(空的可选)。
dateStrs.stream()
.map(s -> {
try {
return Optional.of(dateTimeFormatter.parseDateTime(s));
} catch (Exception e) {
log.error("Illegal format: " + s);
return Optional.empty();
}
})
.flatMap(Optional::stream)
.collect(...);