I was reading about how when possible the java compiler will compile strings concatenated with the "+" operator into instances of StringBuilder, and how this makes it better to use the simple "+" operator since they compile to the same code. (Except when you are building the string in a while loop, in which case it is clearly best to use a StringBuilder.)
I've also read that the .concat method on strings is the worst choice all the time (so much so that it was made into a bug by Findbugs!).
So I decided to test it myself writing a little java class in eclipse. My results surprised me a bit. What I found was that different methods were relatively faster or slower if I complied and ran them in eclipse vs. on the command line.
First my eclipse results were:
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
So in eclipse StringBuilder with the size specified was fastest, followed by .concat (weird), then StringBuilder and "+" concatenation were pretty much the same.
My results on the command line, however, were:
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
So when I compiled and ran from the commnad line the "+" operator was clearly the fastest, followed by String builder with size, then concat, and last was normal StringBuilder!
This doesn't make sense to me. Obviously all the stackoverflow answers I read saying that + operators compile into normal old StringBuilder instances must be outdated.
Does anyone know what's really going on here?
I'm using jdk1.7.0_07, and so far as I can tell both eclipse and my command line are referencing the exact same one. The only difference I know of is eclipse is using "javaw", but from what I've read, that shouldn't make a difference.
Here's my test class if you want to verify I'm not doing anything wrong, but I'm pretty sure it's solid.
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()));
}
}