3

What arguments can You give for the use one or another variant that is better, faster, more correct.

First variant:

StringBuffer sql = new StringBuffer("SELECT DISTINCT f.ID ")
    .append("FROM FIRST_TABLE F ")
        .append("LEFT JOIN SECOND_TABLE s ON f.ID = s.F_ID ")
    .append("WHERE ")
        .append("F.BOOL = 1 ")
        .append("AND S.DATE IS NOT NULL ")
        .append("AND S.CLOSED = 0 ");

Second variant:

String sql = "SELECT DISTINCT f.ID " +
             "FROM FIRST_TABLE F " +
                "LEFT JOIN SECOND_TABLE s ON f.ID = s.F_ID " +
             "WHERE "
                "F.BOOL = 1 " +
                "AND S.DATE IS NOT NULL " +
                "AND S.CLOSED = 0";

*for note: Class String and Class StringBuffer.

Cœur
  • 37,241
  • 25
  • 195
  • 267
old
  • 33
  • 3
  • possible duplicate of [StringBuilder vs String concatenation in toString() in Java](http://stackoverflow.com/questions/1532461/stringbuilder-vs-string-concatenation-in-tostring-in-java) – Barmar Nov 24 '12 at 07:10

2 Answers2

11

The second is better:

  • It's clearer (more of the code has to do with what you want)
  • It's more efficient, as all the concatenation is being done at compile-time

Even if execution-time concatenation was required (e.g. you had a variable in there), the compiled code would use a StringBuilder or StringBuffer where it needed to (depending on the version of Java you're targeting).

Mind you, if you're executing a database query, the efficiency is going to be utterly insignificant.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Ok thx, but what about performance, most interested this part of the question? – old Nov 23 '12 at 13:51
  • @enjoyLife: I covered that in the second bullet: "It's more efficient, as all the concatenation is being done at compile-time" - but take a lesson from the final part... the performance difference would be irrelevant anyway. – Jon Skeet Nov 23 '12 at 13:52
  • @JonSkeet but, using `+` concatination operator would create additional strings, how about that ?? could you please shed some light on that aswell . – PermGenError Nov 23 '12 at 13:57
  • 3
    @GanGnaMStYleOverFlowErroR: No, it wouldn't. In fact, in this case it would generate *fewer* strings, because (for the third time) the concatenation would be done at compile-time. And again, even if it weren't, the compiler would do the right thing. Please read http://www.yoda.arachsys.com/java/strings.html and if you have a specific situation in mind, compile it and then use `javap` to see what would actually happen. – Jon Skeet Nov 23 '12 at 14:00
  • It wouldn't craete additional strings they are all literals so it will get optimised out. If you put each one ina variable and then concatenated based on say some logic, then you'd have an issue. Even then youd, need a much bigger string or being it a lot – Tony Hopkinson Nov 23 '12 at 14:01
  • @JonSkeet amazing, thanks for the link, i always tought using StringBuilder is efficient. BTW, i am a big fan of your answers :) – PermGenError Nov 23 '12 at 14:02
  • Here is an example (using style in the second example): A very large query, need to add another condition, it is known only at run time, if we continue to use concatenation - will create extra string constants, so only one thing - rewrite with StringBuffer, and this is the time. So it may better to make it a rule to use a buffer? – old Nov 23 '12 at 14:04
  • 1
    @enjoyLife: No, you'll still get the string constants with `StringBuffer` or `StringBuilder`. Please read the link in an earlier comment... if you're providing everything in a single expression, then using concatenation will be at least as efficient. `StringBuilder` is better for things like loops, where you *can't* express the whole operation in a single expression. – Jon Skeet Nov 23 '12 at 14:07
  • 1
    +1 Just because using StringBuilder direct is more complicated won't make it more effficient. Using `+` will either a) be simplified at compile time, or b) do exactly the same thing with less code. In any case, no matter how large the string generated is, it is unlikely to matter compared with the cost of passing, parsing, and performing the SQL. – Peter Lawrey Nov 23 '12 at 14:18
  • I do not need to read it, how, what and why - I know. Wanted hear arguments. For themselves stay with his opinion: "if it's probable that request will be constantly changing - use StringBuffer". – old Nov 23 '12 at 14:36
  • @enjoyLife: If you wanted to hear arguments, why would you not read the link which goes into details? If you know "how, what and why", why would you stick with an opinion which prefers a demonstrably less-efficient approach? It sounds like you *want* to use `StringBuffer`, and you'll reject any arguments against it. – Jon Skeet Nov 23 '12 at 14:39
  • @Jon Skeet: why less efficient? In cases where the request is divided into parts and these parts are known only at run time - more efficient use stringBuffer, or not? And sings, if it is probable that a simple query in the future grow into a monster - why would not immediately use the buffer? – old Nov 23 '12 at 14:47
  • 1
    @enjoyLife: Using concatenation, the compiler gets to to what it can at compile-time, and do the rest using a StringBuilder at execution time. So it's *at least* as efficient, and more readable. – Jon Skeet Nov 23 '12 at 14:50
  • @Jon Skeet: Last comment is that I wanted. Make at home a couple of tests to see diff in ms. Спасибо. – old Nov 23 '12 at 15:02
0

You should not be wasting your time worrying about how to concatenate a few strings. Use 2 and keep it clear. Using StringBuilder/buffer is not the mark of a great programmer, if that's what you thought.

Worry about the vaguely defined requirements and the things behind schedule.

Try this ->

long finalTime1 = 0; { long initialTimeTest = System.currentTimeMillis(); for( int index = 0; index < 10000; index++ ){ StringBuilder sb = new StringBuilder("Hello, ").append("World"); System.out.println(sb.toString()); } finalTime1 = System.currentTimeMillis() - initialTimeTest;

}

long finalTime2 = 0; { long initialTimeTest = System.currentTimeMillis(); for( int index = 0; index < 10000; index++ ){ String sb = "Hello, " + "World"; System.out.println( sb ); } finalTime2 = System.currentTimeMillis() - initialTimeTest; }

System.out.println( finalTime1 ); System.out.println( finalTime2 );

Results:

... Hello, World Hello, World 245 148

Did you think string buffer was faster ??

You are breaking the mother of all rules: Keep it Simple. -

For mundane string handling there is no reason why to use StringBuilder. It just adds unnecessary complexity to a mundane task.

We need to think BIG, think in the overall business impact of the module to the project. Discussing whether we shall assemble a few strings with StringBuilder/Builder or String is thinking little, - don't do that.

To your question about performance, I recommend:http://cfd.gmu.edu/~jcebral/academics/csi702/notes/02-optimization.pdf

Alex Vaz
  • 496
  • 5
  • 8