我知道concat,StringBuffer和StringBuilder之间的区别。我知道StringBuffer.toString支持数组的内存问题可能会爆炸内存。我甚至意识到JDK Sun优化包括为初始容量分配2的幂。
但我仍然想知道重用StringBuffer(在toString()中使用)的最佳方法,或者,如果重用StringBuffer是相关的。考虑到内存和速度性能哪一个更好?
public String toString2() {
StringBuffer sb = new StringBuffer(<size>)
... several .append(stuff) ...
sb.trimToSize()
return sb.toString()
}
或
private StringBuffer sb = new StringBuffer(<size>)
public String toString2() {
sb.delete()
sb.setLength(1024)
sb.trimToSize()
... several .append(stuff) ...
return sb.toString()
}
为什么?
答案 0 :(得分:3)
我想说第一个例子肯定更清晰,更容易阅读和更安全 - 这应该几乎总是胜过性能微优化问题。 如果确实存在性能问题和,您可以(通过具体测量)证明它是由这段代码和引起的还可以通过测量证明,在您的本地环境中,第二个示例明显更快,然后 - 而只有 - 您有正当理由使用它。
否则,您的问题没有一般性答案。如果人们声称第二个例子的平均值 n %更快,如果它在你的机器上没有任何差别(因为环境不同,或者因为实际情况),它会对你有什么帮助?你的应用程序中很少调用这段代码吗?
然而,我个人的直觉是,在现代JVM上(阅读:至少在JDK6上,但可能已经在JDK5上),第一个例子可能实际上更快,因为聪明的GC技巧使得分配/释放短 - 生活对象非常便宜。特别是如果您使用StringBuilder
而不是StringBuffer
,它没有同步开销。
答案 1 :(得分:2)
StringBuilder
,StringBuffer
的非同步变体 - 可以直接提供性能提升。 trimToSize
- 您只是强迫StringBuilder
制作新的字符数组。StringBuilder
来节省非常少的资金。StringBuilder
而不是简单的连接表达式 - 例如,您正在迭代某些内容。连接使用StringBuilder
编译基本相同的代码。答案 2 :(得分:0)
如果性能受到关注,我不会在所有esp中使用StringBuffer。
如果你不能确定只有一个线程会调用toString(),我每次都会创建一个StringBuilder。
你遇到的另一个问题是不同的数据类型可能会产生大量垃圾,例如: int
或double
这可以减少您可能获得的任何好处。
我不会回收StringBuilder,我会保持简单。如果你真的需要最大的性能,我会使用一个不同的解决方案,比如直接的ByteBuffer和一个不会产生垃圾的库。
答案 3 :(得分:0)
尝试两种性能测试。与所有性能问题一样,它取决于上下文以及如何调用方法。
几点说明:
StringBuilder
不是线程安全的,但在第一个示例中,线程安全不是问题,因为您的方法不使用字段。这使StringBuilder
比StringBuffer
更快。StringBuffer
,所以你最终会得到一个包含两个调用元素的字符串StringBuffer
(第二个例子),取决于你使用该方法的频率,你实际上可能会保留更多的内存,因为垃圾收集器不会收集{{{}使用的内存1}},可供其他对象使用。