When to use StringBuilder in Java
If you use String concatenation in a loop, something like this,
String s = "";
for (int i = 0; i < 100; i++) {
s += ", " + i;
}
then you should use a StringBuilder
(not StringBuffer
) instead of a String
, because it is much faster and consumes less memory.
If you have a single statement,
String s = "1, " + "2, " + "3, " + "4, " ...;
then you can use String
s, because the compiler will use StringBuilder
automatically.
When to use StringBuilder?
I warmly suggest you to read The Sad Tragedy of Micro-Optimization Theater, by Jeff Atwood.
It treats Simple Concatenation vs. StringBuilder vs. other methods.
Now, if you want to see some numbers and graphs, follow the link ;)
When should you explicitly use a StringBuilder?
It's more general than "inside loops" - it's any time you want to do concatenation over multiple statements, and don't need the intermediate result as a string. For example:
StringBuilder builder = new StringBuilder("Start");
if (someCondition) {
builder.append("Foo");
}
if (someOtherCondition) {
builder.append("Bar");
}
builder.append("End");
String result = builder.toString();
While you could write that as:
String result = "Start" + (someCondition ? "Foo" : "")
+ (someOtherCondition ? "Bar" : "") + "End";
... that becomes hard to read. And if there are more statements within the if
bodies, it may not even be feasible.
To correct something within your question though:
As I understand it, when I do String baz = "foo" + "bar" + "123" the java compiler internally replaces the expression with a StringBuilder.
No, when you write that expression the compiler recognizes that it's a compile-time constant, and replaces it with
String baz = "foobar123";
That's a very good reason not to explicitly use a StringBuilder
- the code above is clearly more efficient at execution time than
String baz = new StringBuilder("foo").append("bar").append("123").toString();
When it isn't a compile-time constant, the Java compiler will perform the concatenation using a StringBuilder
, usually leaving you with easier-to-understand code than with the explicit use of StringBuilder
, but with no performance hit. I suspect your teacher either doesn't properly understand string concatenation, or simply read somewhere else that you should use StringBuilder
without fully understanding when it's appropriate.
In Java, when should I prefer String over StringBuilder vice versa?
You should use String
, because String
objects are cached in an object pool and might deliver better performance when you don't change them.
A StringBuilder
is only useful when you keep on concatenating String
tokens, which shouldn't be the case in a well normalized database table.
The JVM does all sorts of optimizations and chances are that even if you use concatenation the JVM might rewrite that routine to a StringBuilder
version.
How to use StringBuilder wisely?
Modifying immutable structures like string
s must be done by copying the structure, and by that, consuming more memory and slowing the application's run time (also increasing GC
time, etc...).
StringBuilder
comes to solve this problem by using the same mutable object for manipulations.
However:
when concatenating a string
in compile time as the following:
string myString = "123";
myString += "234";
myString += "345";
it will actually compile to something like that:
string myString = string.Concat("123", "234", "345");
this function is faster than working with StringBuilder
for the number of string
s entering the function is known.
so for compile-time-known string
concatenations you should prefer string.Concat()
.
as for unknown number of string
like in the following case:
string myString = "123";
if (Console.ReadLine() == "a")
{
myString += "234";
}
myString += "345";
Now the compiler can't use the string.Concat()
function, however, StringBuilder
appears to be more efficient in time and memory consumption only when the concatenation is done with 6-7 or more strings
.
Bad practice usage:
StringBuilder myString = new StringBuilder("123");
myString.Append("234");
myString.Append("345");
Fine practice usage (note that if
is used):
StringBuilder myString = new StringBuilder("123");
if (Console.ReadLine() == "a")
{
myString.Append("234");
}
myString.Append("345");
Best practice usage (note that while
loop is used):
StringBuilder myString = new StringBuilder("123");
while (Console.ReadLine() == "a")
{
myString.Append("234"); //Average loop times 4~ or more
}
myString.Append("345");
StringBuilder vs String concatenation in toString() in Java
Version 1 is preferable because it is shorter and the compiler will in fact turn it into version 2 - no performance difference whatsoever.
More importantly given we have only 3
properties it might not make a
difference, but at what point do you
switch from concat to builder?
At the point where you're concatenating in a loop - that's usually when the compiler can't substitute StringBuilder
by itself.
How to use stringBuilder
To prevent writing the same (partial) string literal multiple times, you can:
Use a constant for the common part:
if (CollectionUtils.isEmpty(primaryPathList)) {
final String COMMON = "Customer Hierarchy is mandatory field";
if (salesChannelCode.equals(SalesChannelType.HEB_TO_YOU)) {
return Optional.of(COMMON + " for HebToYou.");
} else {
return Optional.of(COMMON + ".");
}
}Build the string using
StringBuilder
:if (CollectionUtils.isEmpty(primaryPathList)) {
StringBuilder buf = new StringBuilder("Customer Hierarchy is mandatory field");
if (salesChannelCode.equals(SalesChannelType.HEB_TO_YOU)) {
buf.append(" for HebToYou");
}
return Optional.of(buf.append('.').toString());
}
Personally, I would keep the code in the question, especially if you ever might need support non-English versions of the text, because in other languages the extra text might not go there.
when to use string over stringbuilder/stringbuffer?
A String offers more functionalities than a StringBuilder. The sole purpose of a StringBuilder, as its name implies, is to build a String.
A String is not less efficient than a StringBuilder (don't know where you got that). It is actually much more efficient, because since it's immutable, you can sefely share references without needing defensive copies.
And most importantly: performance is usually not the main concern anyway. What matters more is correctness, readability, safety, maintainability. And using an immutable String increases all these factors.
If String is so much better than a StringBuilder, then why do we have a StringBuilder? Because there is one use-case where using a StringBuilder is much more efficient than using a String: constructing a String by repeatedly appending parts:
String s = "";
for (String part: collection) {
s += part;
}
The above code is slow because many temporary String objects are created and copied, and must then be GCed. In that case, use a StringBuilder:
StringBuilder builder = new StringBuilder();
for (String part: collection) {
builder.append(part);
}
String s = builder.toString();
Why StringBuilder when there is String?
String
does not allow appending. Each method you invoke on a String
creates a new object and returns it. This is because String
is immutable - it cannot change its internal state.
On the other hand StringBuilder
is mutable. When you call append(..)
it alters the internal char array, rather than creating a new string object.
Thus it is more efficient to have:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
sb.append(i);
}
rather than str += i
, which would create 500 new string objects.
Note that in the example I use a loop. As helios notes in the comments, the compiler automatically translates expressions like String d = a + b + c
to something like
String d = new StringBuilder(a).append(b).append(c).toString();
Note also that there is StringBuffer
in addition to StringBuilder
. The difference is that the former has synchronized methods. If you use it as a local variable, use StringBuilder
. If it happens that it's possible for it to be accessed by multiple threads, use StringBuffer
(that's rarer)
Related Topics
How to Enable Nuget Package Restore in Visual Studio
Websocket Server: Onopen Function on the Web Socket Is Never Called
Assembly Binding Redirect: How and Why
How to Handle Click Event in Button Column in Datagridview
How to Call .Net Methods from Excel Vba
Resharper Wpf Error: "Cannot Resolve Symbol "Myvariable" Due to Unknown Datacontext"
How to Reference Generic Classes and Methods in Xml Documentation
Solid Ffmpeg Wrapper for C#/.Net
C# Thread Termination and Thread.Abort()
How to Mock an Async Repository with Entity Framework Core
The Difference Between Try/Catch/Throw and Try/Catch(E)/Throw E
Prevent Using Dispatcher.Invoke in Wpf Code