2016-04-06 12 views
2

ストリームを使用してリストを別のリストにマップしようとしています。Java8ストリームマップ - すべてのマップ操作が成功したかどうかを確認しますか?

元のリストの一部の要素がマップに失敗します。つまり、マッピング関数は適切な新しい値を見つけることができない可能性があります。

いずれかのマッピングが失敗したかどうかを知りたい。理想的には、障害が発生したら処理を中止することもできます。

私が現在やっていることは次のとおりです。

  • 私はそこストリームからNULL値を削除するには、noマッピングされた値
  • I filter()
  • 私はcollect()はませんし、その後
  • 場合、マッピング機能がnullを返します。結果のサイズと元のリストのサイズを比較します。たとえば、

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

結果がnullの場合、未チェックの例外を 'oldToNew :: get'からスローして、それを外部にキャッチしてみませんか? – Tunaki

+0

@ Tunakiありがとう、それはオプションです。私はそれがエレガンスかパフォーマンスのどちらかを改善するかどうかは分かりません(例外はおそらく高価です)。 – daphshez

+0

変数の名前を 'new'にしないでください。それはうまくいかないでしょう...そして、 'void List 'の戻り値の型はどういう意味ですか? – Holger

答えて

0

あなたは

+3

'NullPointerException'をキャッチすることは決して良い考えではありません。私はそれをお勧めしません。 – Tunaki

1

Objects::requireNonNullにあなたのフィルタを変更して、ストリームの外にNullPointerExceptionをキャッチすることができることは、重くユースケースに依存するため、何の最善の解決策はありません。例えば。ルックアップの失敗が予想されない場合、またはエラー処理が例外をスローすることを意味する場合は、マッピング関数内の最初の失敗したルックアップで例外をスローするだけでよいでしょう。その後、フォローアップコードはエラー状態を気にする必要はありません。

それを処理する別の方法は次のようになります。それは障害のnull値を含む、ほとんど無意味なリストを集めるよう

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); 
} 

これはまだ成功した場合のために最適化されていると考えることができます。しかし、それは失敗の数を伝えることができるという点を持っています(スローマップ関数を使用するのとは異なります)。

詳細なエラー解析は高い優先度を持っている場合、あなたはこのようなソリューション使用できます

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); 
} 

をそれが失敗したルックアップし、正常にマッピングされた値のリストについては、失敗したキーを含む、2つの意味のリストを収集します。両方のリストを返すことができることに注意してください。

関連する問題