Why Alibaba Java Developer's Handbook is not recommended for use in the body of the loop + string stitching?

Before reading "Ali Baba Java Development Manual" and found that there is a proposal for loop stitching string, as follows:

Alibaba Java Development Manual

So how come we first use examples to look at the body of the loop or by using string concatenation with + StringBuilder efficiency bar (JDK version jdk1.8.0_201).

package com.wupx.demo;

/**
 * @author wupx
 * @date 2019/10/23
 */
public class StringConcatDemo {
    public static void main(String[] args) {
        long s1 = System.currentTimeMillis();
        new StringConcatDemo().addMethod();
        System.out.println("使用 + 拼接:" + (System.currentTimeMillis() - s1));

        s1 = System.currentTimeMillis();
        new StringConcatDemo().stringBuilderMethod();
        System.out.println("使用 StringBuilder 拼接:" + (System.currentTimeMillis() - s1));
    }

    public String addMethod() {
        String result = "";
        for (int i = 0; i < 100000; i++) {
            result += (i + "武培轩");
        }
        return result;
    }

    public String stringBuilderMethod() {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < 100000; i++) {
            result.append(i).append("武培轩");
        }
        return result.toString();
    }
}

Execution results are as follows:

使用 + 拼接:29282
使用 StringBuilder 拼接:4

Why is the time difference between the two methods would be so much of it? Let us further study together.

Why StringBuilder so much faster than +?

From the bytecode level look at why the body of the loop string concatenation + faster than StringBuilder so much?

Use javac StringConcatDemo.java command to compile the source file, use the command to view the contents javap -c StringConcatDemo bytecode files.

Wherein the addMethod bytecode () method is as follows:

  public java.lang.String addMethod();
    Code:
       0: ldc           #16                 // String
       2: astore_1
       3: iconst_0
       4: istore_2
       5: iload_2
       6: ldc           #17                 // int 100000
       8: if_icmpge     41
      11: new           #7                  // class java/lang/StringBuilder
      14: dup
      15: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
      18: aload_1
      19: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: iload_2
      23: invokevirtual #18                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      26: ldc           #19                 // String wupx
      28: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      31: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      34: astore_1
      35: iinc          2, 1
      38: goto          5
      41: aload_1
      42: areturn

As can be seen, line 8, line 38 to form a loop: when some conditions are line 8, if not the loop condition, go to the line 41. The compiler do a certain degree of optimization, a new line in 11 StringBuilder object, then line 19, line 23, line 28 was three times called method append (), but every time a new cycle will re StringBuilder object.

Look stringBuilderMethod () method bytecode:

  public java.lang.String stringBuilderMethod();
    Code:
       0: new           #7                  // class java/lang/StringBuilder
       3: dup
       4: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
       7: astore_1
       8: iconst_0
       9: istore_2
      10: iload_2
      11: ldc           #17                 // int 100000
      13: if_icmpge     33
      16: aload_1
      17: iload_2
      18: invokevirtual #18                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      21: ldc           #19                 // String wupx
      23: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      26: pop
      27: iinc          2, 1
      30: goto          10
      33: aload_1
      34: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      37: areturn

13 lines 30 to form a loop line, it can be seen, on line 4 (extracorporeal circulation) to construct good StringBuilder object, only then recycled vivo call append () method.

It can be seen, for loop, a string + splicing, the StringBuilder every time a new, and then converted into the StringBuilder String, then append, and frequent new objects not only time-consuming, It will result in a waste of memory resources. This explains why cycling is not recommended for use in vivo splicing + to the string from the byte code level.

Then again let's look at using the principles of + or StringBuilder string concatenation it.

Use the + string concatenation

In the development of Java, the most simple and common method is the direct use string concatenation + to complete:

String boy = "wupx";
String girl = "huyx";
String love = boy + girl;

The contents are as follows :( decompile decompiler tools used jad)

String boy = "wupx";
String girl = "huyx";
String love = (new StringBuilder()).append(boy).append(girl).toString();

By looking after the decompiled code can be found in the string constant during splicing, it is turned into the StringBuilder String, using its append () method for processing.

So in other words, Java + stitching on the string, its implementation principle is to use a StringBuilder append () to achieve, use the + string concatenation, in fact, just a syntactic sugar provided by Java.

Use StringBuilder string concatenation

StringBuilder second method is to append a common pose a string concatenation.

String class and the like, the StringBuilder class also encapsulates an array of characters is defined as follows:

char[] value;

And String difference is that it is not final, it can be modified. Further, different from the String, a character array that not necessarily all positions have been used, there is an instance variable that indicates the number of characters in the array has been used, defined as follows:

int count;

Which append () method source code as follows:

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

This class inherits AbstractStringBuilder class, look at their append () method:

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

Analyzing string str first splice is not null, and if so, calling appendNull () method of processing, source appendNull () method is as follows:

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

If the string str is not null, it is determined whether the character length of the array exceeds the current length of the array splice, if exceeded, the call Arrays.copyOf () method for expansion and copy source ensureCapacityInternal () method is as follows:

private void ensureCapacityInternal(int minimumCapacity) {
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}

Finally, copy the stitching string str to the target value in the array.

str.getChars(0, len, value, count);

to sum up

In this paper, the loop "Ali Baba Java Development Manual" in the string concatenation recommend starting from the bytecode level, to explain why StringBuilder faster than +, also introduced the + string concatenation and StringBuilder in principle, so when the loop string concatenation, StringBuilder should use the append () to complete the splice.

Guess you like

Origin www.cnblogs.com/wupeixuan/p/11729920.html