最近几天,我通过一些竞争性编程练习,找到了一些问题的解决方案,他们不是通过在for
循环中在控制台中打印文本,而是通过附加一个StringBuilder
彼此之间的文本。首先,我很困惑,但是我尝试了一下,并制定了一些基准。
首次测试:这是在屏幕上打印内容的经典方法:
class TestClass {
public static void main(String args[]) throws Exception {
double startTime = System.currentTimeMillis();
//code
for (int i = 0; i < 1000000; i++) {
System.out.print("test");
}
//code
double endTime = System.currentTimeMillis();
String result = String.format("for loop: %.5f", (endTime-startTime) / 1000);
System.out.print("\n"+result);
}
}
第二项测试:这是StringBuilder
的增强版本:
class TestClass {
public static void main(String args[]) throws Exception {
double startTime = System.currentTimeMillis();
//code
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
sb.append("test");
}
System.out.print(sb);
//code
double endTime = System.currentTimeMillis();
String result = String.format("for loop: %.5f", (endTime - startTime) / 1000);
System.out.print("\n" + result);
}
}
多次运行测试后(使用Intel i5 6500四核3.2 GHZ CPU,Win 10运行它们),结果如下:
first test(for loop): 4,25s
second test(StringBuilder): 0.23s
结果并不意外,因为out.print
已同步,因此每次调用它都会增加一些开销。但是慢将近20倍有点奇怪。
我的问题是:有没有办法进一步改善这一点?
答案 0 :(得分:1)
synchronized
关键字。
第一个测试用例很慢,因为System.out.print
将带来频繁的最小I / O。
您可以使用BufferedWriter
(它的写入方法也是同步的)来减少不必要的I / O:
BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out));
//code
for (int i = 0; i < 1000000; i++) {
log.write("test");
}
for loop: 0.21200
而且,StringBuilder
在内部使用byte[]
进行字符存储。通过将旧值复制到新的byte[]
中来保持附加内容时,此字节数组将增大。
赋予它足够大的容量可能会带来一些效率:
StringBuilder sb = new StringBuilder(1000000 * 10);