我正在从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,在Java中我经常使用带有map和orElseThrow的流.

这两个词中,哪一个在Kotlin 中更惯用?有没有一种更具Kotlin原生性的方法,可以结合我正在寻找的可读性和安全功能?

推荐答案

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

第一个 Select 是可以的,但如果没有let个就更好了(就我个人的口味而言),这可能是因为这里不尊重惯例.X.toY()应该将X转换为Y.有X.toY(Z)将Z转换为Y是很奇怪的.所以我宁愿重新定义toModel的签名,这样接收者就是被转换的东西.这实际上在锁链上发挥得更好:

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

您甚至可以通过在有权访问映射器的作用域中定义扩展toModel来删除retroMapper.

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

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

我想你 Select 的toModel的签名反而鼓励了这种风格.

Kotlin相关问答推荐

Kotlin-删除按钮周围的空格

Flow.state In() 未从其来源接收新值

修改器的属性是什么,我需要更改以使角变圆且宽度更小?喷气背包组合

Jetpack Compose 中的连续重组

在 Kotlin 中,我可以在集合上有一个条件构建器元素吗?

使用空键映射获取

Kotlin - 创建指定长度的随机整数的 ArrayList?

具有多个不同类型来源的 LiveData

Android 在将 androidx 生物识别更新为 1.0.0-alpha04 后崩溃

将 Gradle 子元素与 Kotlin 多平台一起使用

Android数据绑定在自定义视图中注入ViewModel

比较 Kotlin 中的可比对象列表

Kotlin 1.2.21 + SimpleXml 2.3.0 - consume List error (must mark set get method)

使用最新的 com.jakewharton.rxbinding3:rxbinding:3.0.0-alpha2 库时未找到 RxTextView 和其他小部件

Kotlin not nullable值可以为null吗?

使用Dagger 2提供函数依赖性

Tornadofx - 如何在每个实例上将参数传递给 Fragment

大小写敏感性 Kotlin / ignoreCase

Kotlin扩展函数与成员函数?

如何在不绑定ViewModel(MVVM)中的UI的情况下使用android导航?