Kotlin链接收集功能的表现

我是Kotlin的新手,通过使用IDE提供的技巧解决IntelliJ中的简单难题,我正在学习语言。 我写了这段代码(查找最重复的数字):

fun main(args: Array<String>) { val tracer = mutableMapOf<Int,Int>() var currentMaxCount = 0 val numbers = readLine()!!.split(' ').map(String :: toInt) for(number in numbers) { val currentCountOfNum = incrementAndGetCurrentCountOf(number, tracer) currentMaxCount = if(currentCountOfNum > currentMaxCount) currentCountOfNum else currentMaxCount } println(currentMaxCount) } fun incrementAndGetCurrentCountOf(num : Int, tracer: MutableMap<Int,Int>) = if(tracer[num] == null) { tracer.put(num, 1) 1 } else { val newCount = tracer[num]!! + 1 tracer.put(num, newCount) newCount } 

而IDE提示下面的代码:

  var currentMaxCount = 0 for(number in numbers) { val currentCountOfNum = incrementAndGetCurrentCountOf(number, tracer) currentMaxCount = if(currentCountOfNum > currentMaxCount) currentCountOfNum else currentMaxCount } 

改成这样:

 val currentMaxCount = numbers .map { incrementAndGetCurrentCountOf(it, tracer) } .max() ?: 0 

我明白发生了什么事。 但是我想知道如果使用IDE的建议,性能是否会变成O(2n)。 我想到的是O(n)。 我知道这在理论上没有什么区别,但是我想知道Kotlin是否使用任何魔法来保持O(n)的运行时间。 (欢迎任何额外的建议,进一步缩小代码)

TL; DR

是的,这会影响性能,因为这实际上是两个独立的迭代。

在这个特定的上下文中,您可以通过利用专用的maxBy方法来避免额外的迭代:

 numbers.maxBy { incrementAndGetCurrentCountOf(it, tracer) } ?: 0 

记住Kotlin Collections与Java Streams不同,并不是懒惰,所有那些奇特的方法都封装了简单的命令式实现。

因此,在乐观情况下,即使整个处理过程可能由于访问所有元素而被短路, M连锁map调用也会导致O(M * N):

 listOf(1, 2, 3) .map { println(it) }.first() 

这打印:

 1 2 3 

在这种情况下,记住asSequence方法的存在是很重要的,它会创建一个由给定集合支持的延迟评估序列:

 listOf(1, 2, 3).asSequence() .map { println(it) }.first() 

打印:

 1