1

Just curious, which is more efficient?

This:

String a = someString + "." + anotherString;

Or this:

String a = someString + '.' + anotherString;
aberrant80
  • 12,815
  • 8
  • 45
  • 68
  • 4
    You really shouldn't care, unless this is all you do, thousands of times per second, for several hours. – Marius Nov 16 '09 at 06:46
  • 4
    Would have been nice if you pointed out the quotes were different. Spent a good minute starring at that. – mpen Nov 16 '09 at 06:53
  • 1
    @jjnguy - how do you know that? – Stephen C Nov 16 '09 at 07:13
  • 1
    jjnguy most likely has done the same as I, he's microbenchmarked it. Adding a single character is faster because it skips the whole "Make a String out of this, then find the array containing its contents, then append that to this other array" completely. – Esko Nov 16 '09 at 07:15
  • @Esko - how do you know that is what is happening? Did you look at the code? – Stephen C Nov 16 '09 at 07:44
  • the string concat operator '+' needs to have strings on both sides - i m sure the compiler is compiling code that converts the char '.' into a string - which costs more, i m sure, than just hard coding the string "." in there. Plus at compile time, the "." would most likely be interned. – Chii Nov 16 '09 at 08:36

4 Answers4

13

You really shouldn't care, unless this is all you do, thousands of times per second, for several hours.

Rumor has it that using a StringBuilder is the fastest.

Try it both of them, running in a loop, a million times, and logging the time it takes, then report back to the rest of us.

Marius
  • 57,995
  • 32
  • 132
  • 151
  • 2
    The compiler will replace that code with a StringBuilder to do the job. – Tom Nov 16 '09 at 06:52
  • 1
    However the compiler adds *new StringBuilder()* right before the actual append which makes it a lot slower due to object/array memory allocations when running repeatedly in a loop or such. – Esko Nov 16 '09 at 07:31
  • I have followed your suggestions. With 1M the difference was not perceptible. I've tried 10M, with 10M the difference is just a couple of ms. http://stackoverflow.com/questions/1740475/which-is-more-efficient/1740705#1740705 – OscarRyz Nov 16 '09 at 07:54
  • Oscar, you should've added a manual version with StringBuilder already in place to see how that affects the outcome. – Esko Nov 16 '09 at 08:00
  • @Esko: I tried after reading your comment. It look the same to me. I can't tell the difference. – OscarRyz Nov 16 '09 at 08:23
12

Looking at the code for StringBuilder.append and AbstractStringBuilder.append, I would expect the '.' form to be faster.

It has less to do, basically:

  • It doesn't need to do a nullity check, as the char cannot be null
  • It doesn't try to do an optimisation for an empty string being appended
  • It doesn't need to fetch the length to be added - it will always be 1
  • It only has to perform a single assignment into the array rather than a single-iteration loop

Like everyone else though, I wouldn't expect the difference to be significant in real application code.

I don't know whether it would be valid for the Java compiler to realise that what's being appended is a constant string of length 1, and convert that into a character literal instead - or whether it would bother doing so even if it would be valid.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • It certainly is valid for the compiler to do that. Just like it is valid for the compiler to concatenate literal strings. – Stephen C Nov 16 '09 at 07:49
  • @Stephen: Would it have to still intern the "." though? Does the fact that "." appears in the source as a literal mean it has to be interned when the class is loaded? Quite possibly not - but that's the sort of thing they'd have to worry about, potentially. It seems a pretty reasonable optimisation. – Jon Skeet Nov 16 '09 at 07:59
6

They are pretty similar. '.' is slightly faster, but the difference is negligible ( about 20 ms in a 10 million loop ) .

Here's my test:

$cat UsingC.java  UsingS.java  
public class UsingC { 
    public static void main( String [] args ) { 
        String someString  = "";
        String anotherString = "";

        int i = 0;
        while( i++ < 10000000 ) { 
            String a = someString + '.' + anotherString;
        }
    }
}
public class UsingS{ 
    public static void main( String [] args ) { 
        String someString  = "";
        String anotherString = "";

        int i = 0;
        while( i++ < 10000000 ) { 
            String a = someString + "." + anotherString;
        }
    }
}
$for i in 1 2 3 4 5 ; do time java UsingC; done

real    0m1.643s
user    0m1.424s
sys 0m0.108s

real    0m1.670s
user    0m1.468s
sys 0m0.056s

real    0m2.023s
user    0m1.448s
sys 0m0.080s

real    0m1.669s
user    0m1.432s
sys 0m0.088s

real    0m1.674s
user    0m1.416s
sys 0m0.104s
$for i in 1 2 3 4 5 ; do time java UsingS; done

real    0m2.344s
user    0m1.584s
sys 0m0.136s

real    0m2.057s
user    0m1.640s
sys 0m0.084s

real    0m2.112s
user    0m1.732s
sys 0m0.072s

real    0m2.482s
user    0m1.704s
sys 0m0.108s

real    0m2.134s
user    0m1.788s
sys 0m0.072s

You can do an average and/or create a more complex test.

They both use StringBuilder internally anyway.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
  • The only one that actuall answers the question – flybywire Nov 16 '09 at 08:02
  • 1
    Be aware that microbenchmarks can be very tricky and deceiving. See this article by Brian Goetz, for example: http://www.ibm.com/developerworks/library/j-jtp12214/ – Jesper Nov 16 '09 at 08:29
  • It would be sensible to at least check the java byte codes generated to make sure the compile didn't do anything clever. Then all you have to worry about is the JVM :-) – Michael Rutherfurd Nov 17 '09 at 02:39
1

The Java compiler will turn any string concatenation expression into an equivalent sequence of StringBuilder operations. It is safe to assume that the sequence will be close to optimal. Indeed, in this particular example, I'd expect the same (optimal) sequence to be generated in both cases. But even if this is not the case, the difference is likely to be small.

It is only worth bothering about this sort of thing if the profiler tells you that a particular statement is a bottleneck in your code. Premature optimization is pointless (at best) and can even be harmful.

The advice of the Sun folks is that hand optimize Java code can actually be slower code because the resulting bytecode sequence becomes too complex for the JIT compiler to be able to optimize properly. The best advice is just to write the code simply and trust the Javac and JIT compilers to do a good job.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216