kotlin中Int.toString()的时间复杂性



我想知道kotlin中默认方法toString((的时间复杂性。是O(1(还是O(n(。我找了一些,但没有找到答案。例如:如果我想将int数组转换为String,我使用了:

var s = ""
array.forEach{
s+= it.toString()
}

但是如果数组大小是10^4,我会得到TLE。如果我不使用toString((,那么我就不会得到TLE。我知道还有其他方法可以将Int数组转换为String。但我想知道kotlin中默认toString((方法的时间复杂性。TIA-

Kotlin对toString()的复杂性没有任何保证。

它可能因对象而异;每个对象都必须实现它,因此它可能取决于对象的结构及其字符串表示。在很多情况下,我想它在字符串的长度上可能是线性的,但你不应该依赖它。但这确实意味着,具有短字符串表示的对象可能只需要很少的时间,不值得担心。

特别是,对于Ints,字符串的大小很可能是线性的(因此与数字的对数成比例(。但这对任何现实世界的项目来说都不太可能意义重大。

然而,的意义可能在于构造的String对象的数量,因为这些对象占用内存,然后加速下一次垃圾收集。(即使对于不管"死"对象的数量如何都需要相同时间的垃圾收集器,拥有大量临时对象也会导致它们更频繁地运行。在高通量系统中,这可能非常重要。(

这当然是问题中的代码的一个问题,它在循环中每次都会创建两个新的String实例!一个是调用toString()的结果;另一个是将其附加到CCD_ 6的结果。(虽然前者总是很小,但后者每次都会增长,这使得这个在空间需求上是二次的。(这就是为什么在循环中进行字符串串联通常是个坏主意

当然,String是不可变的,但它有一个可变的助手类StringBuilder。因此最好使用StringBuilder来累积结果,然后在最后创建String(如果需要(:

val sb = StringBuilder()
array.forEach {
sb.append(it.toString())
}
val s = sb.toString()

在这种情况下,您可以做得更好,因为StringBuilder会过载append()。因此,您可以直接附加一个Int,而无需创建一个中间String

val sb = StringBuilder()
array.forEach {
sb.append(it)
}
val s = sb.toString()

创建的唯一临时对象是StringBuilder的内部数组;随着内容的增长,它将需要重新分配其数组来容纳它们。如果您可以估计最终结果的大小,那么您可以预先确定StringBuilder的大小,以避免这种开销。

不过,在实践中,您可能根本不会使用循环;您可以使用joinToString(),它可以为您完成所有功能:

val s = array.joinToString("")

它更短、更简单、更易于阅读,的性能可能与手动编码版本一样好。Kotlin有很多有用的扩展函数;熟悉它们是非常值得的!

如果您需要尽可能高效地自己构造复杂的字符串表示,而不是使用toString()来创建每个部分,每个相关类都可以有一个以StringBuilder为参数的方法,并将其部分附加到该方法中。这可以让您构建一个任意复杂的字符串,而根本不需要任何String实例!

最新更新