性能:Java的String.format
可能重复:
如果性能很重要,我应该使用Java的String.format()吗?
我想知道在Java应用程序中使用String.format
而不是StringBuilder
…所以,我只是编写一个简单的测试,如下所示:
public static void main(String[] args) { int i = 0; Long start = System.currentTimeMillis(); while (i < 10000) { String s = String.format("test %d", i); i++; } System.out.println(System.currentTimeMillis() - start); i = 0; start = System.currentTimeMillis(); while (i < 10000) { String s = new StringBuilder().append("test ").append(i).toString(); i++; } System.out.println(System.currentTimeMillis() - start); }
结果在哪里:
238 15
因此,如果我的测试有效, StringBuilder
比String.format
更快。 好。 现在,我开始思考String.format
工作原理。 它是一个简单的字符串连接,如"test " + i
?
StringBuilder
连接和String.format
之间有什么区别? 有没有像String.format
一样简单的方法,像StringBuilder
一样快?
我写了一个快速卡尺基准来比较String.format()
与StringBuilder
, StringBuffer
,普通String
+
运算符, String.replace()
和String.concat()
方法:
public class StringFormatBenchmark extends SimpleBenchmark { public void timeStringFormat(int reps) { while (--reps >= 0) { String s = String.format("test %d", reps); } } public void timeStringBuilder(int reps) { while (--reps >= 0) { String s = new StringBuilder("test ").append(reps).toString(); } } public void timeStringBuffer(int reps) { while (--reps >= 0) { String s = new StringBuffer("test ").append(reps).toString(); } } public void timeStringPlusOperator(int reps) { while (--reps >= 0) { String s = "test " + reps; } } public void timeReplace(int reps) { while (--reps >= 0) { String s = "test {}".replace("{}", String.valueOf(reps)); } } public void timeStringConcat(int reps) { while (--reps >= 0) { String s = "test ".concat(String.valueOf(reps)); } } public static void main(String[] args) { new Runner().run(StringFormatBenchmark.class.getName()); } }
结果如下(Java 1.6.0_26-b03,Ubuntu,32位):
显然String.format()
要慢得多(按一个数量级)。 StringBuffer
也比StringBuilder
慢得多(正如我们所教导的那样)。 最后, StringBuilder
和String
+
运算符几乎完全相同,因为它们编译为非常相似的字节码。 String.concat()
有点慢。
如果简单连接就足够了,也不要使用String.replace()
。
String.format相对较慢,但通常不够快。
如果更简单,我会使用格式,除非您在分析应用程序时看到性能问题。
注意:示例中的String.format需要大约24微秒,并且还没有完全预热。 我会忽略前10K迭代。
恕我直言"test " + i
在这种情况下是最简单的。
我已经运行了一个测试后的JVM预热(一旦编译了方法)并获得了类似的结果,StringBuilder的速度提高了30多倍。
格式:943
stringbuilder:26
public class TestPerf { private static int NUM_RUN; public static void main(String[] args) { NUM_RUN = 100_000; //warm up for (int i = 0; i < 10; i++) { method1(); method2(); } System.gc(); System.out.println("Starting"); long sum = 0; long start = System.nanoTime(); for (int i = 0; i < 10; i++) { sum += method1(); } long end = System.nanoTime(); System.out.println("format: " + (end - start) / 1000000); System.gc(); start = System.nanoTime(); for (int i = 0; i < 10; i++) { sum += method2(); } end = System.nanoTime(); System.out.println("stringbuilder: " + (end - start) / 1000000); System.out.println(sum); } private static int method1() { int sum = 0; for (int i = 0; i < NUM_RUN; i++) { String s = String.format("test %d", i); sum += s.length(); } return sum; } private static int method2() { int sum = 0; for (int i = 0; i < NUM_RUN; i++) { String s = new StringBuilder().append("test ").append(i).toString(); sum += s.length(); } return sum; } }