我们必须一直为日志输出构建字符串等等。在JDK版本中,我们已经学习了什么时候使用StringBuffer(许多追加,线程安全)和StringBuilder(许多追加,非线程安全)。
使用String.format()有什么建议?它是有效的,还是我们被迫坚持在性能很重要的一行程序中使用连接?
例如,丑陋的老式风格,
String s = "What do you get if you multiply " + varSix + " by " + varNine + "?";
vs.整洁的新样式(字符串。格式,可能更慢),
String s = String.format("What do you get if you multiply %d by %d?", varSix, varNine);
注意:我的特定用例是代码中的数百个“一行”日志字符串。它们不涉及循环,所以StringBuilder太重量级了。我对String.format()特别感兴趣。
在您的示例中,性能可能没有太大不同,但还有其他问题需要考虑:即内存碎片。连接操作也在创建一个新字符串,即使它是临时的(GC需要时间,而且工作量更大)。String.format()可读性更强,涉及的碎片更少。
此外,如果你经常使用特定的格式,不要忘记你可以直接使用Formatter()类(所有String.format()所做的是实例化一个使用Formatter实例)。
此外,还应该注意其他一些事情:小心使用substring()。例如:
String getSmallString() {
String largeString = // load from file; say 2M in size
return largeString.substring(100, 300);
}
这个大字符串仍然在内存中,因为这就是Java子字符串的工作方式。一个更好的版本是:
return new String(largeString.substring(100, 300));
or
return String.format("%s", largeString.substring(100, 300));
如果你同时做其他事情,第二种形式可能更有用。
Java的字符串。格式如下:
它解析格式字符串,分解成一个格式块列表
它迭代格式块,呈现为一个StringBuilder,这基本上是一个数组,根据需要调整自己的大小,通过复制到一个新的数组。这是必要的,因为我们还不知道分配最终字符串的大小
StringBuilder.toString()将他的内部缓冲区复制到一个新的String中
如果这个数据的最终目的地是一个流(例如,渲染一个网页或写入一个文件),你可以将格式块直接组装到你的流中:
new PrintStream(outputStream, autoFlush, encoding).format("hello {0}", "world");
我推测优化器将优化掉格式字符串处理。如果是这样,就剩下了与手动展开String相同的平摊性能。格式转换为StringBuilder。
在您的示例中,性能可能没有太大不同,但还有其他问题需要考虑:即内存碎片。连接操作也在创建一个新字符串,即使它是临时的(GC需要时间,而且工作量更大)。String.format()可读性更强,涉及的碎片更少。
此外,如果你经常使用特定的格式,不要忘记你可以直接使用Formatter()类(所有String.format()所做的是实例化一个使用Formatter实例)。
此外,还应该注意其他一些事情:小心使用substring()。例如:
String getSmallString() {
String largeString = // load from file; say 2M in size
return largeString.substring(100, 300);
}
这个大字符串仍然在内存中,因为这就是Java子字符串的工作方式。一个更好的版本是:
return new String(largeString.substring(100, 300));
or
return String.format("%s", largeString.substring(100, 300));
如果你同时做其他事情,第二种形式可能更有用。