2016-11-09 73 views
1

我有一列表String代表序列化數據,我想map對象的列表。我使用下面的代碼:映射,除非例外

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

然而,有時有分析錯誤和流只是停止,我希望能夠恢復列表,直到故障點。例如,如果在項目7發生錯誤,我希望doOtherStuff可以獲取已成功處理的6個項目。

什麼是最習慣的方式來做到這一點?我可以過濾列表,看看解析是否會成功,但這是一個昂貴的操作,要做兩次。

回答

5

您可以將異常視爲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

您可以使用'mapNotNull'而不是'map'和'filterNotNull'來降低從2N到N的複雜度。 – mfulton26

+0

我相信mapNotNull會忽略列表中的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,像Jayson Minardexample,你可以映射你需要的任何異常null

strings.mapWhileNotNull { 
    try { 
     gson.fromJson(it, Model::class.java) 
    } catch (e: JsonSyntaxException) { 
     null 
    } 
} 
// .doOtherStuff