2016-04-06 40 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); 
} 

它收集兩種意義的列表,包含未能查找失敗的關鍵,併成功地映射值的列表。請注意,這兩個列表可能會返回。