2016-04-06 105 views
2

我想将一个列表映射到另一个使用流。Java8流映射 - 检查所有映射操作是否成功?

原始列表的某些元素无法映射。也就是说,映射函数可能无法找到合适的新值。

我想知道是否有任何映射失败。理想情况下,我也想在发生故障时停止处理。

什么我目前做的是:

  • 映射函数返回null如果没有映射值
  • filter()从流
  • collect()删除空,然后
  • 我比较结果的大小和原始列表的大小。

例如:

List<String> func(List<String> old, Map<String, String> oldToNew) 
{ 
    List<String> holger = old.stream() 
          .map(oldToNew::get) 
          .filter(Objects::nonNull) 
          .collect(Collectors.toList); 

    if (holger.size() < old.size()) { 
     // ... appropriate error handling code ... 
    } 
    else { 
     return holger; 
    } 
} 

这是不是很优雅。而且,即使整件事情都失败了,一切都会被处理。

有关更好的方法的建议吗? 或者我应该完全沟渠并使用好的旧环路?

+1

如果结果为空,为什么不从'oldToNew :: get'中抛出未经检查的异常,并将其捕获到外部? – Tunaki

+0

@Tunaki谢谢,这是一个选项。我不知道这是否会改善优雅或表现(因为例外是昂贵的)。 – daphshez

+0

不要命名变量'new'。这将无法正常工作......'void List '的返回类型应该是什么意思? – Holger

回答

0

则可以将过滤器更改为Objects::requireNonNull,赶上一个NullPointerException流

+3

捕捉'NullPointerException'永远不是一个好主意。我不会推荐。 – Tunaki

1

外没有最好的解决方案,因为这在很大程度上取决于使用情况。例如。如果预计查找失败的可能性不大,或者错误处理意味着抛出异常,那么在映射函数中首次失败查找时抛出异常可能确实是一个不错的选择。然后,没有后续代码必须关心错误条件。

处理它可能是另一种方式:

List<String> func(List<String> old, Map<String, String> oldToNew) { 
    Map<Boolean,List<String>> map=old.stream() 
     .map(oldToNew::get) 
     .collect(Collectors.partitioningBy(Objects::nonNull)); 
    List<String> failed=map.get(false); 
    if(!failed.isEmpty()) 
     throw new IllegalStateException(failed.size()+" lookups failed"); 
    return map.get(true); 
} 

这还是可以考虑被认为是成功的情况下优化,它收集包含失败null值大多是毫无意义的列表。但它能够告诉失败的次数(与使用投掷地图函数不同)。

如果详细的错误分析,具有高优先级,你可以使用一个解决方案是这样的:

List<String> func(List<String> old, Map<String, String> oldToNew) { 
    Map<Boolean,List<String>> map=old.stream() 
     .map(s -> new AbstractMap.SimpleImmutableEntry<>(s, oldToNew.get(s))) 
     .collect(Collectors.partitioningBy(e -> e.getValue()!=null, 
      Collectors.mapping(e -> Optional.ofNullable(e.getValue()).orElse(e.getKey()), 
       Collectors.toList()))); 
    List<String> failed=map.get(false); 
    if(!failed.isEmpty()) 
     throw new IllegalStateException("The following key(s) failed: "+failed); 
    return map.get(true); 
} 

它收集两种意义的列表,包含未能查找失败的关键,并成功地映射值的列表。请注意,这两个列表可能会返回。