2016-04-27 88 views
1

我有一个字符串列表,每个字符串都代表一个日期。我想将此列表映射到DateTime对象列表中;但是,如果任何字符串无效(引发异常),我想记录一个错误,但不会将它添加到最终列表中。有没有办法同时进行过滤和映射?同时过滤和映射java流

这是我目前有:

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(...); 

有没有办法做到这一点,这样我就不必parseDateTime两次,每次元素?

谢谢

回答

2

您可以先将字符串映射到其解析日期。如果遇到无效的日期字符串,则记录它并返回空值。

然后在第二步中筛选非空日期。

0

以相反的顺序进行操作。

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(...); 

在这里,您可以在单一操作中做所有事情。

0

更新为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(...);