2016-11-09 10 views
1

Stringのリストは、オブジェクトのリストにmapとしたいシリアル化されたデータを表しています。時々そこに解析エラーとストリームは、ちょうど停止している私は障害点までリストを回復することができるしたいと思います、しかし例外を除いてマッピング

strings.map { gson.fromJson(it, Model::class.java) } 
// .doOtherStuff 

:私は、次のコードを使用します。たとえば、項目7でエラーが発生した場合は、doOtherStuffに正常に処理された6項目を取得します。

これを行う最も慣用的な方法は何ですか?私は、構文解析が成功するかどうかを見るためにリストをフィルタリングすることができますが、それは高価な操作が2回実行されていることです。

答えて

5

例外をnullとして扱い、NULLをフィルタリングすることができます。

val models = modelsInJson.map { json -> 
    try { 
     gson.fromJson(json, Model::class.java) 
    } catch (ex: WhateverException) { 
     // TODO: logging here? 
     null 
    } 
}.filterNotNull() 

あなたが処理したいエラーの種類のための正しいものでWhateverExceptionを交換し、他のエラーは、まだ処理を停止することができます。

+0

これはパフォーマンスの影響を知っていますか?私が使用しているリストはかなり大きいです...私はそれが2N最悪の場合になることを認識しますが、コンパイラが何とかそれを最適化したかどうか疑問に思っています。 –

+1

'filterNotNull'で' map'の代わりに 'mapNotNull'を使用して2NからNまでの複雑さを減らすことができます。 – mfulton26

+0

mapNotNullはlistのnull値を無視しますが、そうではありません。彼らはちょうど解析できません。 –

1

あなたが探しているのは、maptakeWhileの組み合わせのようです。あなたはいつでも自分のロールを張ることができます。例えば以下は、mapNotNulltakeWhileの源から構成されている:

inline fun <T, R : Any> Iterable<T>.mapWhileNotNull(transform: (T) -> R?): List<R> { 
    return mapWhileNotNullTo(ArrayList<R>(), transform) 
} 

inline fun <T, R : Any, C : MutableCollection<in R>> Iterable<T>.mapWhileNotNullTo(destination: C, transform: (T) -> R?): C { 
    for (element in this) { 
     val transformed = transform(element) 
     if (transformed == null) { 
      break 
     } else { 
      destination.add(transformed) 
     } 
    } 
    return destination 
} 

今、あなたはnullになり変換呼び出しまでのiterableをマッピングする可能性があるため、Jayson Minardexampleのように、あなたはあなたがする必要があるものは何でも例外マッピングすることができますnull

strings.mapWhileNotNull { 
    try { 
     gson.fromJson(it, Model::class.java) 
    } catch (e: JsonSyntaxException) { 
     null 
    } 
} 
// .doOtherStuff 
関連する問題