9

Basically, I was wondering which approach is better practice,

for(int i = 0; i < 10000; i++){
    System.out.print("blah");
}
System.out.println("");

or

String over_9000_blahs = "";
for(int i = 0; i < 10000; i++){
    over_9000_blahs += "blah";
}
System.out.println(over_9000_blahs);

or is there an even better way that I'm not aware of?

Jiri Tousek
  • 12,211
  • 5
  • 29
  • 43
ScegfOd
  • 402
  • 3
  • 12
  • This is a micro-optimization if you are looking at performance. If you have a need to have a string use the concatenation if you just need it output just output it. – nerdlyist Feb 06 '17 at 20:32
  • Probably the second one but using a string builder instead of creating new `String` instances over and over again. – luk2302 Feb 06 '17 at 20:33
  • When output is buffered, direct output will be faster. Concatenation requires repeated copies of the string, and will be really slow (stringbuilder will make that much faster) – that other guy Feb 06 '17 at 20:36
  • 1
    @luk2303 a `+=` on `String` gets converted to a `StringBuilder` by the compiler under the hood. http://stackoverflow.com/a/47628/6194785 – jseashell Feb 06 '17 at 20:41
  • The first one is much better. Try to implement the second case for an infinite loop. – Lyubomyr Shaydariv Feb 06 '17 at 20:49
  • 2
    So applicability to a requirement that wasn't stated (infinite loops) makes one way universally better? Nope. – Mark Adelsberger Feb 06 '17 at 20:55
  • Well, it does not require to produce a huge intermediate state as it's stated in the second option. What if increase the number of iterations or decrease the size of heap? How to predict? – Lyubomyr Shaydariv Feb 06 '17 at 21:01
  • 3
    @j.seashell but not properly within a loop. In a loop each iteration creates a new StringBuilder instance - not really a good idea... As you can see if you scroll down on the post you linked. The actual answer you linked does not have anything to do with this question, but the one by ckpwong is relevant. And there you can clearly read that manual StringBuilder outside the loop is the way to go. (And both answers say basically the same ting) – luk2302 Feb 07 '17 at 12:08

5 Answers5

6

Since you are only writing to the System.out the first approach is better BUT if performance are important to you use the method below (System.out.println is synchronized and using locking - can read more about it here and here ) .

If you want to use the "big string" later or improve performance, it's cleaner to use StringBuilder. (see below) , anycase String + will translate to StringBuilder by the compiler (more details here)

        StringBuilder stringBuilder = new StringBuilder();
        for(int i = 0; i < 10000; i++){
            stringBuilder.append("bla");
        }
        System.out.println(stringBuilder.toString());
Community
  • 1
  • 1
Mzf
  • 5,210
  • 2
  • 24
  • 37
  • 1
    @Mzf a `+=` on `String` gets converted to a `StringBuilder` by the compiler under the hood http://stackoverflow.com/a/47628/6194785 – jseashell Feb 06 '17 at 20:43
  • 1
    @j.seashell but as far as I know, `+=` would create a new `StringBuilder` for each iteration. The compiler might perform further optimizations, but I don't think they are guaranteed. – Hulk Feb 07 '17 at 08:33
  • You're lucky that `i` is not much bigger than 10000. – Lyubomyr Shaydariv Feb 07 '17 at 09:01
6

You want to use StringBuilder if you're concatenating string in a (larger count) loop.

for(int i = 0; i < 10000; i++){
    over_9000_blahs += "blah";
}

What this does is for each iteration:

  • Creates a new StringBuilder internally with internal char array large enough to accommodate the intermediate result (over_9000_blahs)
  • Copies the characters from over_9000_blahs into the internal array
  • Copies the characters from "blah"
  • Creates a new String, copying the characters from internal array again

So that is two copies of the increasingly long string per iteration - that means quadratic time complexity.


Since System.out.println() might be synchronized, there's a chance that calling it repeatedly will be slower than using StringBuilder (but my guess would be it won't be slower than concatenating the string in the loop using +=).

So the StringBuilder approach should be the best of the three.

Community
  • 1
  • 1
Jiri Tousek
  • 12,211
  • 5
  • 29
  • 43
2

By performance order:

  1. StringBuilder - The fastest. Basically, it just adding the words into a array of characters. When capacity is not enough then it multiply it. Should occur no more than log(10000) times.

  2. System.out.print - It has bad performance comparing to StringBuilder because we need to lock out 10000 times. In addition, print creates new char[writeBufferSize] 10000 times while in the StringBuilder option we do all that 1 time only!

  3. Concatenating strings. Creating many (and later also big) objects, starting some 'i' the memory management will impact the performance badly.

EDIT:

To be more accurate, because the question was about the difference between option 2 and option 3 and it is very clear why Stringbuilder is fast.

We can say that every iteration in the second approach takes K time, because the code is the same and the length of the string is the same for every iteration. At the end of execution, the second option will take 10000*K time for 10000 iterations. We can't say the same about the third approach because the length of the string is always increasing for each iteration. So the time for allocating the objects and garbage collecting them increasing. What I'm trying to say is that the execution time does not increased linearly in the third option. So it is possible that for low NumberOfIterations we won't see the difference between the two last approaches. But we know that starting a specific NumberOfIterations the second option is always better than the third one.

elirandav
  • 1,913
  • 19
  • 27
0

In this case, I'd say the first one is better. Java uses StringBuilders for string concatenations to increase performance, but since Java doesn't know you are repeatedly doing concatenations with a loop like in the second case, the first case would be better.

MacStation
  • 411
  • 4
  • 20
0

If you want only to sysout your values - the result is same.

Second option will create many strings in memory, which GC (Garbage Collector) will take care of. (But in newer versions of Java this problem don't occurs because concating will be transformed behined the scenes to StringBuilder solution below)

If you want use your string later, after sysout, you should check StringBuilder class and append method:

StringBuilder sb = new StringBuilder();
for(int i = 0; i < 10000; i++){
    sb.append("blah");
}
System.out.println(sb);
ByeBye
  • 6,650
  • 5
  • 30
  • 63
  • not sure that you are right (about the GC) take a look herer :http://stackoverflow.com/questions/10078912/best-practices-performance-mixing-stringbuilder-append-with-string-concat . behind the scenes it's translate to StringBuilder – Mzf Feb 06 '17 at 20:42
  • 1
    It is not true in all cases. But in most cases you are right – ByeBye Feb 06 '17 at 20:44
  • @ByeBye a `+=` on `String` gets converted to a `StringBuilder` by the compiler under the hood http://stackoverflow.com/a/47628/6194785 – jseashell Feb 06 '17 at 20:44
  • 1
    Sure, `+=` gets converted to a `StringBuilder` behind the scenes in *some* versions of Java (not all). Regardless, the concept is the same when referring to better practice (don't create unnecessary strings). This answer should be updated to disclose that `StringBuilder` is sometimes secretly used, and then everyone can be happy. – Michael Yaworski Feb 06 '17 at 20:52