我正在阅读有关 java 编译器如何在可能的情况下将与“+”运算符连接的字符串编译为 StringBuilder 的实例,以及如何更好地使用简单的“+”运算符,因为它们编译为相同的代码。(除非您在 while 循环中构建字符串,在这种情况下,显然最好使用 StringBuilder。)
我还读到字符串上的 .concat 方法一直是最糟糕的选择(以至于它被Findbugs变成了一个错误!)。
所以我决定自己在eclipse中编写一个小java类来测试它。我的结果让我有点吃惊。我发现,如果我在 Eclipse 和命令行中编译并运行它们,不同的方法相对更快或更慢。
首先我的日食结果是:
the total millis to concatenate with + was: 12154
the total millis to concatenate with .concat was: 8840
the total millis to concatenate with StringBuilder was: 11350
the total millis to concatenate with StringBuilder with a specified size was: 5611
所以在eclipse中指定大小的StringBuilder最快,其次是.concat(奇怪),然后StringBuilder和“+”连接几乎相同。
然而,我在命令行上的结果是:
the total millis to concatenate with + was: 4139
the total millis to concatenate with .concat was: 8590
the total millis to concatenate with StringBuilder was: 10888
the total millis to concatenate with StringBuilder with a specified size was: 6033
因此,当我从命令行编译并运行时,“+”运算符显然是最快的,其次是带有大小的 String builder,然后是 concat,最后是普通的 StringBuilder!
这对我来说没有意义。显然,我读到的所有 stackoverflow 答案都说 + 运算符编译成普通的旧 StringBuilder 实例必须是过时的。
有谁知道这里到底发生了什么?
我正在使用 jdk1.7.0_07,据我所知,eclipse 和我的命令行都引用了完全相同的一个。我知道的唯一区别是 eclipse 是使用“javaw”,但从我读过的内容来看,这不应该有所作为。
如果您想验证我没有做错任何事情,这是我的测试课程,但我很确定它是可靠的。
public class Test {
static final int LOOPS = 100000000;
static final String FIRST_STRING = "This is such";
static final String SECOND_STRING = " an awesomely cool ";
static final String THIRD_STRING = "to write string.";
/**
* @param args
*/
public static void main(String[] args) {
Test.plusOperator();
Test.dotConcat();
Test.stringBuilder();
Test.stringBuilderSizeSpecified();
}
public static void plusOperator() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
String toPrint = localOne + localTwo + localThree;
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with + was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
public static void stringBuilder() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
StringBuilder toBuild = new StringBuilder()
.append(localOne)
.append(localTwo)
.append(localThree);
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with StringBuilder was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
public static void stringBuilderSizeSpecified() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
StringBuilder toBuild = new StringBuilder(50)
.append(localOne)
.append(localTwo)
.append(localThree);
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with StringBuilder with a specified size was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
public static void dotConcat() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
String toPrint = localOne.concat(localTwo).concat(localThree);
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with .concat was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
}