我写了以下代码:
val src = (0 until 1000000).toList()
val dest = ArrayList<Double>(src.size / 2 + 1)
for (i in src)
{
if (i % 2 == 0) dest.add(Math.sqrt(i.toDouble()))
}
Run Code Online (Sandbox Code Playgroud)
IntellJ(在我的例子中是AndroidStudio)问我是否要用stdlib中的操作替换for循环.这导致以下代码:
val src = (0 until 1000000).toList()
val dest = ArrayList<Double>(src.size / 2 + 1)
src.filter { it % 2 == 0 }
.mapTo(dest) { Math.sqrt(it.toDouble()) }
Run Code Online (Sandbox Code Playgroud)
现在我必须说,我喜欢改变的代码.当我提出类似的情况时,我发现写入比循环更容易.但是在阅读了filter函数的功能后,我意识到与for循环相比,这是一个很慢的代码.filterfunction创建一个新列表,其中仅包含src中与谓词匹配的元素.因此,在stdlib版本的代码中创建了另外一个列表和一个循环.对于小型列表来说,它可能并不重要,但总的来说这听起来不是一个好的选择.特别是如果要连接更多这样的方法,你可以通过编写for循环来获得许多可以避免的额外循环.
我的问题是什么被认为是Kotlin的良好做法.我应该坚持使用循环还是我错过了一些东西而且它不起作用,因为我觉得它有效.
gle*_*e8e 14
如果您担心性能,那么您需要的是Sequence.例如,您的上述代码将是
val src = (0 until 1000000).toList()
val dest = ArrayList<Double>(src.size / 2 + 1)
src.asSequence()
.filter { it % 2 == 0 }
.mapTo(dest) { Math.sqrt(it.toDouble()) }
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,filter返回另一个Sequence代表中间步骤的代码.什么都没有真正创建,没有对象或数组创建(除了新的Sequence包装器).只有在mapTo调用终端操作符时才会创建生成的集合.
如果你已经学过java 8流,你可能会发现上面的解释有些熟悉.实际上,Sequence大致相当于java 8 Stream的kotlin.它们具有相似的目的和性能特征.唯一的区别是Sequence不适合使用ForkJoinPool,因此更容易实现.
当涉及多个步骤或集合可能很大时,建议使用Sequence而不是普通.filter {...}.mapTo{...}.我还建议您使用Sequence表单而不是命令式表单,因为它更容易理解.当数据处理涉及5个或更多步骤时,命令形式可能变得复杂,因此难以理解.如果只有一个步骤,则不需要a Sequence,因为它只会创建垃圾并且没有任何用处.
| 归档时间: |
|
| 查看次数: |
2661 次 |
| 最近记录: |