与StringBuilder一起使用DecimalFormat

问题描述

StringBuilder 一起使用 DecimalFormat 实例的最有效方法是什么?例如,在循环中将数字附加到字符串后。有format(long number,StringBuffer toAppendTo,FieldPosition pos),但使用的是 StringBuffer 而不是 StringBuilder ,因此它不兼容,还有formatToCharacterIterator(Object obj),但两者必须为迭代器创建一个对象,并且不能与基本类型一起使用,因此它还需要其他潜在的装箱操作。

在我看来,调用format(long number)来生成一个字符串并将其附加到 StringBuilder 是最简单的选择,但是不得不创建一个字符串来附加它似乎有点失败 StringBuilder 的目的。真的没有其他选择吗?

编辑:我决定进行一些测量,以查看这些选项之间的性能差异。基于OpenJDK实现,似乎所有方法最终都会路由到format(long,StringBuffer,FieldPosition)format(double,FieldPosition)(大的 BigInteger BigDecimal ),这样看来,当只附加数字时,使用 StringBuffer 这种方式总是会更快。

事实上,在我的机器上直接使用 StringBuffer 比通过 StringBuilder 和中间字符串快20%。但是,当不进行数字格式化并且仅附加字符串时,情况正好相反–然后 StringBuffer 慢20%。但是考虑到格式化数字要比单纯追加字符串慢大约5倍,而 StringBuilder 似乎只有在追加的次数明显多于格式化时才更有效率。

解决方法

除非您可以确定额外的String和StringBuffer创建是应用程序中的实际瓶颈,否则我怀疑您不必要地担心。的确,如果我们可以重新发明JDK的历史,那么这些调用可能会被定义为采用Appendable。但是,当在Java 5中添加StringBuilder和Appendable并认为不值得时,作者可能已经考虑过添加相应的方法。

请记住,在现代JVM中,临时对象的创建和处理不会像以前那样具有性能开销。另外,NumberFormat的各种形式(包括DecimalFormat)实际上提供了一个内部“快速路径”(请参见fastFormat()方法),从而避免了您提到的StringBuffer创建(尽管不是临时的String创建)。 JVM通常也会像您在此处进行的那样优化无竞争的同步。

如果一个配置文件确实表明DecimalFormat.foramt()是您的应用程序的瓶颈,那么您可能需要考虑实现一种特定的方法以包括所需的优化。但我怀疑您会发现这实际上不是问题。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...