2016-11-09 48 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