Kotlin 中使用带有 map 和 orElseThrow 的流的惯用方式是什么?

问题描述 投票:0回答:1

我正在从 Java 过渡到 Kotlin,并习惯使用 Java Streams。我有以下两个 Kotlin 代码片段,它们基本上执行相同的操作:它们尝试通过客户端调用创建回顾并将其映射到模型。如果创建或映射失败,则应抛出异常。

解决方案1:

val createdRetro = 
retroClient.createRetro(newRetroDto)?.let(retroMapper::toModel)
    ?: throw Exception("Could not create retro")

解决方案2:

val createdRetro2 = 
sequenceOf(retroClient.createRetro(newRetroDto))
    .filterNotNull()
    .map { retroMapper.toModel(it) }
    .firstOrNull() ?: throw Exception("Could not create retro")

对于来自 Java 的我来说,第二种方法似乎更熟悉,我经常将 Streams 与 map 和 orElseThrow 结合使用。

以下哪个在 Kotlin 中更惯用?是否有一种更加 Kotlin 原生的方法,可以结合我正在寻找的可读性和安全功能?

java kotlin java-stream option-type
1个回答
0
投票

我当然不会为此创建一个序列,所以选项 2 在我看来是不可能的,除非你确实想处理多个元素。

第一个选项还可以,但如果没有

let
(就我个人口味而言)会更好,这可能是因为这里不尊重约定。
X.toY()
应该将 X 转换为 Y。
X.toY(Z)
将 Z 转换为 Y 很奇怪。所以我宁愿重新定义
toModel
的签名,这样接收器就是被转换的东西。实际上,这在链中效果更好:

val createdRetro = retroClient.createRetro(newRetroDto)?.toModel(retroMapper)
    ?: throw Exception("Could not create retro")

您甚至可以通过在有权访问映射器的范围中定义扩展名

retroMapper
来删除
toModel

请注意,您也可以在不更改其他任何内容的情况下简单地提前失败:

val rawCreatedRetro = retroClient.createRetro(newRetroDto)
    ?: throw Exception("Could not create retro")
val createdRetro = retroMapper.toModel(rawCreatedRetro)
© www.soinside.com 2019 - 2024. All rights reserved.