X Tutup
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Devaka Cooray
  • Jeanne Boyarsky
  • Paul Clapham
  • Tim Cooke
Sheriffs:
  • Ron McLeod
Saloon Keepers:
  • Tim Holloway
Bartenders:

Confusion about Java String immutability and performance

 
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Question:
Hi everyone,
I am learning Java and I am a bit confused about how String immutability works and how it affects performance.
For example, when I write code like this:
Java
Copy code
String s = "Hello";
s = s + " World";
I read that Strings are immutable, so does this mean a new object is created every time I modify the string?
If that is the case, then:
How does this impact performance in large loops?
Should I always use StringBuilder instead of String for concatenation?
In what situations is it okay to use normal String concatenation?
I would appreciate a simple explanation with examples.
Thank you!
 
Marshal
Posts: 82157
593
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Kamalika Seenivasan wrote:. . . Strings are immutable, so does this mean a new object is created every time I modify the string?

You can't modify the String. What you are doing is creating a new String. goes out of scope quickly.

. . . How does this impact performance in large loops?

Adversely. You won't notice anything until your loop runs several thousand times; in Java9 (2019) the implementation of the loop was changed; I have forgotten the details, but such a loop run about 100× faster than it had done in Java8. You will still find it is painfully slow to concatenate 100,000 objects, and using a StringBuilder runs thousands of times faster. A StringBuilder runs even fasterif you can estimate the size of the final result and enter a size for the backing array into its constructor.


Should I always use StringBuilder instead of String for concatenation?

No. If any of the operands to the + operator in the following code is a String, the repeated us of + is probably the best way to concatenate everything:-

. . . a simple explanation . . .

That form of code allows the javac tool to apply whichever optimisation is currently programmed as the best at the moment.

[Warning]Blinding you with science follows [/Warning]

If you use the javap tool, you can see details of the implementation:-

campbell@campbellCampbellsComputer$ javac StringConcatenator.java
campbell@campbellsComputer$ java StringConcatenator CodeRanch is brilliant .
Concatenated Strings:-
CodeRanchisbrilliant.

The part you are interested strats with line 14. You will see it calls a static method on this class which creates aCallSite object, and that is as much as I know about it. See if you can understand the details. In Java8 or previous, you can use the following instructions:-

javac -source 8 --target 8 StringConcatenator.java
javap -c StringConcatenator

(You have to change var to String in the code, line 10. Ignore the warning messages.)You will then see that the loop uses a StringBuilder object (line 30), which is created every time the loop runs; later it goes out of scope and has to be deleted by the garbage collector program whenever you start to run low on heap memory. That is much slower than the newer technique.
 
Saloon Keeper
Posts: 29101
215
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Java Strings are interesting things.

If you use a concatenation operator on two or more Strings/string constants whose value is known at compile time, the compiler will perform an ancient and honourable operation called constant folding. Constant folding does all the work as part of compiling the code rather than each time the code runs. It's also done for other things such as reducing a "1 + 4" " integer constant expression to give a value of 5.

Using a StringBuilder in such a context will probably be actually less efficient, since it's harder to optimise at compile time.

As a general rule, a StringBuilder will result in more efficient code when concatenating run-time values, although in some cases the compiler will internally optimise a concatenation operator into a StringBuilder operation.

To make things even more fun, there's this thing called interning. When the Java VM loads and digests a class, the string constants go into an internal String pool where duplicate strings are eliminated for the sake of better storage usage. The "intern" String method can be used to force an ordinary String to be added to the intern pool (or to return an existing intern copy). From a general computation, an intern String and a standard heap String are indistinguishable, as only their location is different.

Another trick when doing substrings is to take an existing String character array and use it (via pointer references) as a shared character sequence for two different String objects. Whether/if this is done and how aggressively will depend on the vendor and implementation of a particular Java compiler/VM distro. It is again something that would not be visible to the casual developer.
 
Master Rancher
Posts: 5291
87
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There are definitely times when using string concatenation by + or += in a loop is a very bad idea.  And there are other times when it's not a problem at all, or even where it may be faster (and probably more readable) than using a StringBuilder.  So how do we know which is which?  The key is to look for the variable on the left hand side - when you add something to a string using +, what is being used to store the result?  Some variable, usually.  And the big, important question here is: does that same variable also appear on the right hand side of the equals sigh?  Almost always, that will happen at the very beginning of the right hand side (after =).  For example:

Here were see "message" is on both the left and right sides of the equals.  That's bad, for string concatenation.  Especially because it's inside a loop.  Every time we add something to the message, we have to recopy the previous message contents, and it gets bigger each time.  That's the situation we really want to avoid.  This also means that if you have string concatenation in an expression with +=, it's almost guaranteed to be bad, because += automatically means the same variable is on both sides of the =.  I.e.

is exactly equivalent to

Both of which are bad.
In comparison, if you have string concatenation where the variable on the left does not appear on the right, that's almost always not a problem.  E.g.

That's not a problem, even in a loop.  Because it's not making the message bigger each time through the loop.

This also means, if there is no = sign where the string concatenation occurs, then there's no problem, because there is no mechanism to take the output of the concatenation and put it back as input the next time through the loop.  So:

This is exactly equivalent the the previous code example - we just skipped having a separate variable for "message", before calling send().  But it works the same way, which is fine.

Of course, I'm assuming that the send() method does not have some problem of its own.  This is just a discussion of whether there is any problem in the code shown.
 
Tim Holloway
Saloon Keeper
Posts: 29101
215
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There's another optimisation trick called "loop unrolling". In some cases - generally small loops - the optimiser may replace the test-and-jump that defines a loop with a brute-force repetition. Given the right context, then, an optimiser might even internally swap out the repeated String concatenations with a single StringBuilder and a chain of appends.

That's a pretty extreme form of optimisation, but not an impossible one, so the best advice is to A) keep it simple, as the more creative you get, the less likely an optimiser witll be able to help you and - more importantly - B) don't code yourself into a corner where minor optimisations become a major design factor.

That second part is important because with current technology, it's almost always more economical to simply throw bigger hardware at a problem than to micro-optimise and in any event, the most effective optimisations don't come from twiddling small things, but by choosing the optimal algorithm for the big picture. A favorite real-world example of that from my own experience was a case where the "efficient" QuickSort ran at worst-case performance because the data was already mostly sorted; the optimal algorithm for that case was a Shell-Metzner sort.

That said, if you're repeatedly re-creating very long Strings, you're going to have a hard time, so plan to avoid that. Optimisers can only do so much even under ideal conditions.
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Java Strings are immutable, meaning once created their value can’t change. This ensures thread-safety and allows string pooling, improving memory efficiency. For performance, avoid repeated concatenation in loops—use StringBuilder or String Buffer, which are mutable and faster for multiple modifications.
 
Campbell Ritchie
Marshal
Posts: 82157
593
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:. . . times when using string concatenation by + or += . . . may be faster . . .

A long time ago, I was told that using plain simple + is proably the best way to implement String concatenation outwith any loops because the JVM or javac can implement whichever optimisation is fastest, if optimisation is an issue at all.
 
Campbell Ritchie
Marshal
Posts: 82157
593
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
WS, welcome to the Ranch
 
Campbell Ritchie
Marshal
Posts: 82157
593
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

waqas sb wrote:. . . in loops—use StringBuilder or String Buffer . . .

Do you know he difference between those two types?
 
Mike Simmons
Master Rancher
Posts: 5291
87
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

waqas sb wrote:For performance, avoid repeated concatenation in loops



Campbell Ritchie wrote:A long time ago, I was told that using plain simple + is proably the best way to implement String concatenation outwith any loops



These both miss the point I was making in my past post.  Using string concatenation (with +) inside a loop can be perfectly fine - as long as the expression isn't concatenating to a String variable defined outside the loop, and adding more to that String each time it goes through the loop.  If it's using a variable defined inside the loop, no problem at all.  Like this:

Each time it creates a message, it's a new message.  It's never concatenating something on to an old message.  That's the key that makes this use  of concatenation inside a loop perfectly all right.
reply
    Bookmark Topic Watch Topic
  • New Topic
X Tutup