2

In terms of efficiency and raw performance, if I want to print out a list of strings should I concatenate them all first, then print them, or should I print them one by one?

For example:

List<String> strings = whatever;

//Option 1
for(String s : strings){
   System.out.println(s);
}

//Option 2
String output = "";
for(String s : strings){
   output = output + s + "\n";
}
System.out.print(output);

Is option 1 or option 2 faster?

wgoodall01
  • 1,855
  • 14
  • 21
  • 1
    In this specific implementation, option 1 would be faster. String concatenation in a loop takes more time. – Luiggi Mendoza Aug 25 '14 at 22:16
  • 2
    What does profiler say? – kan Aug 25 '14 at 22:16
  • 1
    Have you tried both ways? It is easiest to test differences if you use really large strings. That said, (1) will probably be faster, if you understand the underlying Java String implementation. Enough faster? I don't know: what is your motivation to do this? – Nathaniel Ford Aug 25 '14 at 22:16
  • 1
    As a rule of thumb, less calls to IO is faster on OS level, but I am not sure how it is implemented in java. Regarding string concatination, it can be done much more efficiently than your suggestion using a StringBuider – amit Aug 25 '14 at 22:18
  • I would guess that for small list concatenation would be faster(but with using StringBuilder). But for large list the size of the string would play a bigger role and could slow down the Builder. Tests with profiler should help - maybe the optimal way would be to print concataneted parts(by i.e. 100-1000 elements). – Michał Schielmann Aug 25 '14 at 22:24
  • Probably more important than efficiency and raw performance is testability. Option 2 is easier to test (you can delegate the string-building to its own method, then make assertions against the string it returns). – Carl Manaster Aug 25 '14 at 22:27

5 Answers5

0

Option 1 is linear in complexity. Option 2 is quadratic, since strings are immutable and it has to create a new string for every time you append something at the end. Therefore, given a large enough strings array, option 1 will always be faster.

It's difficult to measure, since System.out.println uses a different thread to print the line. It's been known though that the call is quite heavy. Therefore, if I were to guess, I think the following would be the best option:

StringBuilder output = new StringBuilder();
for(String s : strings) {
    output.append(s);
}
System.out.println(s);

This makes it linear and quite fast.

Ghostkeeper
  • 2,830
  • 1
  • 15
  • 27
0

I would recommend trying both ways and seeing which is faster. String concatenation is an expensive operation, but so is System.out.println(), so the right thing to do could very well depend on your use case. Personally, I've had issues with trying to print Strings that are too long, but also with println() being too expensive.

Alex Kleiman
  • 709
  • 5
  • 14
0

I assume that the strings contained in the list are final.

In case they are not declared as final, they should be.

In case they are declared as final, i think the second choice will be faster, since the concatenation of strings is done with final variables.

Víctor Albertos
  • 8,093
  • 5
  • 43
  • 71
0

Option 2 is significantly slower.

In Option 1, using the 'for each' loop is equivalent to using an iterator to access the List. It's a read-only access and doesn't require any extra storage in memory, nothing need to be copy and pasted nor take any space on the memeory, so it's not generating any 'waste'. Click here to learn about How does the Java 'for each' loop work?

Compare to Option 2, you created a new object just to be garbage collected when you do this.

String output = "";

As well as every time when this

output = output + s + "\n";

happens, a new String object is created, and copy and pasted from the older one. And the reference 'output' moved on to work for the new String object, leaving the old one sitting alone in the memory, waiting to be garbage collected. This happens because the property of java String, it's immutable meaning once it's created, it can never be changed. aka all String are created final. Learn more about Immutability of Strings in Java

As of the System.out.println() function, it will only take constant time, so in terms of Big O notation analysis, it's neglect-able.

This question is a very good example why you should use StringBuilder or StringBuffer to manipulate String in java. Why StringBuilder when there is String?

Community
  • 1
  • 1
Fionie
  • 11
  • 1
0

First, for any performance issues, you can simply mesure it yourself with

System.currentTimeMillis();

you should run it before the loop and after the loop and check the result.

Second, more important: your second option is a NO NO! NEVER DO THAT. Let me give you an analogy: Say you're painting the road white lines. You put your bucket of paint in point 0 and then you draw your first line. Then, you go back to your bucket to get more paint and move to the 2nd line. Then you go back to point 0 to get more paint and move to draw the 3rd line. And so forth and so forth.

In a way, instead of moving the bucket with you - you're leaving it in point 0. You'll be very very slow at one point. Hint: use StringBuilder or StringBuffer

enter image description here

adhg
  • 10,437
  • 12
  • 58
  • 94