3 回答
TA贡献1111条经验 获得超0个赞
Java 11 或 Java 12 版本中没有任何东西StringBuilder
可以做到这一点。
真正的问题是您可能从中获得的性能提升对您有多重要。 分析您的应用程序以了解这种不需要的重新分配是否对您的应用程序的整体性能有显着影响。
如果它要产生重大影响,您可以实现自己的版本StringBuilder
(扩展相同的接口以实现兼容性)。
或者,如果您准备等待,您可以下载 OpenJDK 源代码并开发/构建/测试扩展以StringBuilder
……并将其作为补丁提交以供考虑。(如果您包含了显示出明显性能优势的基准,那将有助于增加包含的机会。)
TA贡献1827条经验 获得超9个赞
对此做了更多研究后,我为我自己的问题提供了另一个答案(Stack Overflow 说回答你自己的问题是完全可以接受的。)
正如Slawomir 所说,无论如何,StringBuilder 都会使用 Latin1 进行初始化。因此,假设您主要使用俄语、中文、印地语或希腊语等语言写作。您想要构建一个已知其最大大小的字符串,因此您使用初始容量参数:
StringBuilder sb = new StringBuilder(4096); sb.append("Здравствуйте!"); // Should easily fit in 4 kilobytes, right?
然而,上面的调用append
会丢弃您之前初始化的 4KB 缓冲区并分配一个新缓冲区。您构造了具有初始容量的 StringBuilder 以避免重新分配缓冲区,但 StringBuilder 无论如何都重新分配了它。它重新分配了它,即使它已经足够大了!
解决方法是使用 JVM 选项运行 java -XX:-CompactStrings
。
如果您始终使用其中一种语言,那么您的字符串无论如何都会使用 UTF-16,因此在启动时关闭字符串压缩将减少检查您提供的每个字符串以查看它是否可以使用 Latin1 编码存储的开销。
另请参阅Heinz Kabutz 于 2019 年 5 月 29 日在保加利亚 jPrime 上的演讲,其中他导致 StringBuilder 由于此“功能”而耗尽内存。
TA贡献1784条经验 获得超8个赞
似乎没有明显的。如果您想影响 StringBuffer 初始化的方式,我的建议是创建一个实用程序“初始化器”来实现CharSequence
和使用相应的 StringBuilder 构造函数。您可以使用它来传达任何长度和字符内容,并且 StringBuilder 内部应该足够聪明以接受它。
不过,看看 OpenJDK 11 的实现,它似乎无论如何都要从 Latin1 开始。某种形式的重新分配似乎总是会发生。
添加回答
举报