我想知道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()
的复杂性没有任何保证。
它可能因对象而异;每个对象都必须实现它,因此它可能取决于对象的结构及其字符串表示。在很多情况下,我想它在字符串的长度上可能是线性的,但你不应该依赖它。但这确实意味着,具有短字符串表示的对象可能只需要很少的时间,不值得担心。
特别是,对于Int
s,字符串的大小很可能是线性的(因此与数字的对数成比例(。但这对任何现实世界的项目来说都不太可能意义重大。
然而,的意义可能在于构造的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
实例!