Second brother, I am a sophomore this year. I saw a paragraph in the Alibaba Java Development Manual you shared: “In the loop body, it is better to use the Append method of StringBuilder instead of the + operator to concatenate strings.” Why on earth, I always use the ‘+’ operator ah! Can you write an article to analyze it when brother is free?

Just yesterday, a reader named Xiao CAI said this to me on wechat.

I saw this wechat first feeling is: small dishes you are too dishes, this do not know why ah! I’m sure you feel the same way reading this.

But honestly, during my first two years as a programmer, I didn’t know why. When string concatenation occurs, append the “+” operator, regardless of whether it is in the body of the loop. Compared to Xiao CAI, I was not as lucky as he was, and I had a helpful second brother who could share this valuable development manual.

Since I’m so eager to share, I’d rather the good guys follow through, right? I will write a serious article, to solve the confusion of small dishes.

01. The + operator

In terms of posture, the “+” operator has to be the most common type of string concatenation.

String chenmo = "silence "; String wanger = "wanger "; System.out.println(chenmo + wanger);Copy the code

Let’s decompile this code using JAD.

String chenmo = "\u6C89\u9ED8"; // Silence String wanger = "\u738B\u4E8C"; Println ((new StringBuilder(String.Valueof (chenmo))).AppEnd (wanger).toString()));Copy the code

Heck, the original compilation replaced the “+” operator with the Append method of StringBuilder. In other words, the “+” operator is just a formalism for concatenating strings, making it easier for developers to use, simpler to look at, and smoother to read. It’s a kind of Java syntactic candy.

02, StringBuilder

Aside from the “+” operator, StringBuilder’s append method is the second commonly used string concatenation position.

Append: StringBuilder appEnd: StringBuilder appEnd: StringBuilder appEnd

public StringBuilder append(String str) {
    super.append(str);
    return this;
}
Copy the code

AbstractStringBuilder > AbstractStringBuilder > AbstractStringBuilder < AbstractStringBuilder >

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}
Copy the code

1) Check whether the concatenated string is null, if so, treat it as string “NULL”. The appendNull method has the following source code:

private AbstractStringBuilder appendNull() {
    int c = count;
    ensureCapacityInternal(c + 4);
    final char[] value = this.value;
    value[c++] = 'n';
    value[c++] = 'u';
    value[c++] = 'l';
    value[c++] = 'l';
    count = c;
    return this;
}
Copy the code

2) Whether the length of the character array after concatenation exceeds the current value. If so, expand and copy it. The ensureCapacityInternal method is as follows:

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}
Copy the code

3) Copy the concatenated string STR into the destination array value.

str.getChars(0, len, value, count)
Copy the code

03, StringBuffer

StringBuffer comes first and StringBuilder comes second, so they’re kind of like twins, they have everything they need, except that the older StringBuffer is thread-safe because it takes two more breaths of fresh air.

public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}
Copy the code

The append method of the StringBuffer class uses the synchronized keyword to override toStringCache = null.

Synchronized is a very familiar keyword in Java and is a type of synchronization lock. The methods it decorates are called synchronous methods and are thread-safe.

04. The concat method of String

In terms of posture alone, the concat method of The String class is like the Append of the StringBuilder class.

String chenmo = "silence "; String wanger = "wanger "; System.out.println(chenmo.concat(wanger));Copy the code

While writing this article, I suddenly had a wonderful idea. Suppose there are two lines of code:

chenmo += wanger
chenmo = chenmo.concat(wanger)
Copy the code

How different are they?

Chenmo += wanger = new StringBuilder(String.Valueof (chenmo))).appEnd (wanger).toString().

To explore the difference between the “+” operator and concat, look at the difference between the append and concat methods.

The source code for the append method has been analyzed before. Let’s take a look at the source of the concat method.

public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    int len = value.length;
    char buf[] = Arrays.copyOf(value, len + otherLen);
    str.getChars(buf, len);
    return new String(buf, true);
}
Copy the code

1) If the length of the concatenated string is 0, return the string before concatenation.

if (otherLen == 0) {
    return this;
}
Copy the code

2) Copy the character array value of the original string into the variable buf array.

char buf[] = Arrays.copyOf(value, len + otherLen);
Copy the code

3) Copy the concatenated string STR into the character array buf and return the new string object.

str.getChars(buf, len);
return new String(buf, true);
Copy the code

Through source code analysis, we can roughly draw the following conclusions:

1) If the concatenated string is null, a NullPointerException will be thrown during concat and the “+” operator will be treated as a “NULL” string.

2) Concat is more efficient if the concatenated string is an empty string (“”). After all, you don’t need a New StringBuilder object.

3) Concat becomes less efficient if a large number of strings are concatenated, because the more string objects you create, the more overhead.

Attention!!

Weakly ask ah, still have the classmate that uses JSP? The “+” operator is not allowed to concatenate strings in EL expressions. Instead, concat is used.

${chenmo.concat('-').concat(wanger)}
Copy the code

Join method of String class

JDK 1.8 provides a new String concatenation posture: the String class adds a static method called JOIN.

String chenmo = "silence "; String wanger = "wanger "; String cmower = String.join("", chenmo, wanger); System.out.println(cmower);Copy the code

The first argument is a string concatenation, for example:

String message = String. Join (" - ", "two", "tete yao", "interesting");Copy the code

The output is: wang – t – t – interesting

Let’s look at the source of the join method:

public static String join(CharSequence delimiter, CharSequence... elements) {
    Objects.requireNonNull(delimiter);
    Objects.requireNonNull(elements);
    // Number of elements not likely worth Arrays.stream overhead.
    StringJoiner joiner = new StringJoiner(delimiter);
    for (CharSequence cs: elements) {
        joiner.add(cs);
    }
    return joiner.toString();
}
Copy the code

There’s a new class called StringJoiner, and it looks like a 6, and it’s very easy to read. StringJoiner is a class in the java.util package that constructs a sequence of characters rejoined by delimiters. Limited by space, this article will not do too much introduction, interested students can go to know.

06, StringUtils. Join

Practical projects, when we deal with string, often use this class — org.apache.com mons. Lang3. StringUtils, the class of the join method is a kind of new posture of string concatenation.

String chenmo = "silence "; String wanger = "wanger "; StringUtils.join(chenmo, wanger);Copy the code

This method is better at concatenating strings from arrays without worrying about NullPointerExceptions.

StringUtils.join(null)            = null
StringUtils.join([])              = ""
StringUtils.join([null])          = ""
StringUtils.join(["a", "b", "c"]) = "abc"
StringUtils.join([null, "", "a"]) = "a"
Copy the code

Looking at the source code, we can see that the StringBuilder is still used internally.

public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) { if (array == null) { return null; } if (separator == null) { separator = EMPTY; } final StringBuilder buf = new StringBuilder(noOfItems * 16); for (int i = startIndex; i < endIndex; i++) { if (i > startIndex) { buf.append(separator); } if (array[i] ! = null) { buf.append(array[i]); } } return buf.toString(); }Copy the code

When you read this, you will have such a feeling: I rely on (sound to be prolonged), did not expect ah did not expect, string stitching fully 6 postures ah, back home at night must try one by one.

07. Give xiao CAI a reply

I’m sure when Xiao CAI reads this, he’ll understand why Alibaba doesn’t recommend using the “+” operator for string concatenation in the for loop.

Let’s look at two pieces of code.

In the first paragraph, the “+” operator is used in the for loop.

String result = "";
for (int i = 0; i < 100000; i++) {
    result += "六六六";
}
Copy the code

In the second paragraph, append is used in the for loop.

StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100000; I++) {sb.append(" 666 "); }Copy the code

How long will each of these pieces of code take? What I found on my iMac:

1) The first piece of code takes 6,212 milliseconds to complete

2) The second piece of code takes 1 millisecond to complete

That’s a big fucking gap! Why is that?

I’m sure many of you already have an answer: the first for loop creates a large number of StringBuilder objects, while the second code ends up with a single StringBuilder object.

08, finally

Thank you for your reading. It is not easy to be original. If you like it, please click 👍, which will be my strongest motivation for writing. If you find this article helpful and interesting, please pay attention to my public account “Silent King ii”. Reply “666” also has 500G high quality teaching video to send (classified).