When to Use Stringbuilder in Java

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 Strings, because the compiler will use StringBuilder automatically.

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.

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.

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 ;)

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.

Should one use StringBuilder in a recursive function?

You can add StringBuilder to recursive method:

public String recursive(int n, StringBuilder sb) {
String retStr = "s";
if (n==0) {
return retStr;
}
else {
return sb.append(retStr).append(recursive(n-1, sb)).toString();
}
}

and call it

recursive(100, new StringBuilder());

Append String directly or use StringBuilder

As a programmer we should always care about the readability of our code and the first case looks quite readable to me than the second one.

Now if your question is which one should I choose ?

Than answer is any of them and you should not bother for this.StringBuilder only make difference with loop, other than that currently both of the cases would be almost same.

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();


Related Topics



Leave a reply



Submit