在Kotlin有多种方法来做同一件事,这是为什么呢
val viaSequence = items.asSequence()
.filter { it%2 == 0 }
.map { it*2 }
.toList()
println(viaSequence)
val viaIterable = items.asIterable()
.filter { it%2 == 0 }
.map { it*2 }
.toList()
println(viaIterable)
val viaStream = items.stream()
.filter { it%2 == 0 }
.map { it*2 }
.toList()
println(viaStream)
我知道下面的代码在每一步都创建了一个列表,这会增加GC的负载,因此应该避免:
items.filter { it%2 == 0 }.map { it*2 }
2条答案
按热度按时间uplii1fm1#
流来自于Java,Java中没有内联函数,因此流是在Java集合上使用这些函数链的唯一方法。Kotlin可以直接在Iterables上执行,这在很多情况下对性能更好,因为不需要创建中间的Stream对象。
Kotlin将Sequences作为Streams的替代方案,具有以下优点:
Sequence.groupBy
和Stream.collect
)。sequence
builder可以让你在一个协程中用简单的顺序语法创建一个复杂的惰性项目序列,非常强大。另一个答案提到了流的优点。
Nice article comparing them here.
s3fp2yjn2#
你的三种变通办法之一与使用清单本身相同:
在这里,你调用的
filter
函数就像你刚刚调用的items.filter
一样。List本身就是一个Iterable
,所以它是被调用的Iterable过滤器。这个过滤器查看所有可用的元素,并返回一个完整的列表。所以问题是为什么我们同时有流和序列。
流是Java的一部分。许多终端操作产生
Optional
。其他操作,如toList()
,将产生非空安全的平台类型,如List<Integer!>
。另一方面,序列是Kotlin的本机类型,它们可以与Kotlin自己的编译时空安全特性一起使用。此外,序列在Kotlin的非JVM变体中可用。Kotlin的设计者可能必须创建一个新的类,因为如果他们刚刚向Stream添加了新的操作,例如作为扩展函数,它们会与现有的名称冲突(例如
max()
在Java中返回Optional
,这对Kotlin来说并不理想,但选择一个不同于自然名称max
的名称也不理想)。因此,在大多数情况下,您应该更喜欢序列,因为它们更符合Kotlin习惯用法。然而,Java Streams可以做一些序列尚不可用的事情(例如,SummaryStatistics或并行操作)。当您需要一个仅在Streams中可用的操作,但您有一个序列时,您可以使用
asStream()
将序列转换为流(反之亦然)。Streams的另一个优点是,您可以使用IntStream之类的基元流,以避免不必要的装箱/取消装箱。