StringBuilder and StringBuffer parsing (required for Baidu interview optimization)

Source: Internet
Author: User

StringBuilder is an API provided by Java 5 and later. It is not thread-safe, while StringBuffer is an API previously provided by Java. It is thread-safe. Therefore, StringBuilder is more efficient, let's talk about several methods of string connection in java today ..

This article is mainly about a previous article Baidu interview question, which needs to be optimized due to the character string connection problem in the loop ..

A string is one of the most common data structures in Java programs. In Java, the String class has been overloaded with "+ ". That is to say, strings can be directly connected using "+", as shown in the following code:

  1. String s = "abc" + "ddd";

But is this really good? Of course, you cannot simply answer yes or no. According to the specific situation
Yes. A StringBuilder class is provided in Java (this class is provided only in J2SE5 and later versions, and the StringBuffer class is used in earlier versions). This class can also play the role of "+. So which one should we use?

Let's take a look at the following code:

  1. package string;  public class TestSimplePlus  {      public static void main(String[] args)      {          String s = "abc";          String ss = "ok" + s + "xyz" + 5;          System.out.println(ss);      }  }

     

The above code will output the correct results. On the surface, there is no difference between using "+" for strings and integers, but is it true? Let's take a look at the nature of this Code.

First, we use a decompilation tool (such as jdk javap or jad) to decompile TestSimplePlus into a Java Byte Code. In this article, we will use jad for decompilation. The command is as follows:

Jad-o-a-s d. java TestSimplePlus. class

The decompiled code is as follows:

  1. package string;  import java.io.PrintStream;  public class TestSimplePlus  {      public TestSimplePlus()      {      //    0    0:aload_0               //    1    1:invokespecial   #8   < Method void Object()>      //    2    4:return                }      public static void main(String args[])      {        String s = "abc";      //    0    0:ldc1            #16  < String "abc">      //    1    2:astore_1                String ss = (new StringBuilder("ok")).append(s).append("xyz").append(5).toString();      //    2    3:new             #18  < Class StringBuilder>      //    3    6:dup                   //    4    7:ldc1            #20  < String "ok">      //    5    9:invokespecial   #22  < Method void StringBuilder(String)>      //    6   12:aload_1               //    7   13:invokevirtual   #25  < Method StringBuilder StringBuilder.append(String)>      //    8   16:ldc1            #29  < String "xyz">      //    9   18:invokevirtual   #25  < Method StringBuilder StringBuilder.append(String)>      //   10   21:iconst_5              //   11   22:invokevirtual   #31  < Method StringBuilder StringBuilder.append(int)>      //   12   25:invokevirtual   #34  < Method String StringBuilder.toString()>      //   13   28:astore_2                System.out.println(ss);      //   14   29:getstatic       #38  < Field PrintStream System.out>      //   15   32:aload_2               //   16   33:invokevirtual   #44  < Method void PrintStream.println(String)>      //   17   36:return                }  }

     

Readers may be confused with the above Java bytecode, but don't worry. The purpose of this article is not to explain the Java Byte Code. Therefore, we do not need to understand the meaning of the specific bytecode.

One of the advantages of using jad for decompilation is that you can generate bytecode and source code at the same time. In this way, we can conduct a comparative study. From the code above, it is easy to see that although "+" is used in the source program, "+" is still converted into StringBuilder during compilation. Therefore, we can draw a conclusion that the StringBuilder class is actually used in Java regardless of the method used for string connection.

So can we use the "+" and StringBuilder classes based on this conclusion to achieve the same effect? This should be explained in two aspects. If it is explained from the running result, "+" and StringBuilder are completely equivalent. However, from the perspective of running efficiency and resource consumption, there will be a big difference between them.

Of course, if the line expression of the connected string is very simple (the above sequence structure), then the "+" and StringBuilder classes are basically the same, but if the structure is complicated, such as using loops to connect strings, the generated Java Byte Code will be very different. Let's take a look at the following code:

  1. package string;   import java.util.*;   public class TestComplexPlus   {       public static void main(String[] args)       {           String s = "";           Random rand = new Random();           for (int i = 0; i <  10; i++)           {               s = s + rand.nextInt(1000) + " ";           }           System.out.println(s);       }   }

     

The above Code returns the compiled Java Byte Code as follows:

  1. package string;  import java.io.PrintStream;  import java.util.Random;  public class TestComplexPlus  {      public TestComplexPlus()      {      //    0    0:aload_0               //    1    1:invokespecial   #8   < Method void Object()>      //    2    4:return                }      public static void main(String args[])      {          String s = "";      //    0    0:ldc1            #16  < String "">      //    1    2:astore_1                  Random rand = new Random();      //    2    3:new             #18  < Class Random>      //    3    6:dup                   //    4    7:invokespecial   #20  < Method void Random()>      //    5   10:astore_2                  for(int i = 0; i <  10; i++)      //*   6   11:iconst_0              //*   7   12:istore_3              //*   8   13:goto            49           s = (new StringBuilder(String.valueOf(s))).append(rand.nextInt(1000)).append(" ").toString();      //    9   16:new             #21  < Class StringBuilder>      //   10   19:dup                   //   11   20:aload_1               //   12   21:invokestatic    #23  < Method String String.valueOf(Object)>      //   13   24:invokespecial   #29  < Method void StringBuilder(String)>      //   14   27:aload_2               //   15   28:sipush          1000      //   16   31:invokevirtual   #32  < Method int Random.nextInt(int)>      //   17   34:invokevirtual   #36  < Method StringBuilder StringBuilder.append(int)>      //   18   37:ldc1            #40  < String " ">      //   19   39:invokevirtual   #42  < Method StringBuilder StringBuilder.append(String)>      //   20   42:invokevirtual   #45  < Method String StringBuilder.toString()>      //   21   45:astore_1              //   22   46:iinc            3  1      //   23   49:iload_3               //   24   50:bipush          10      //   25   52:icmplt          16          System.out.println(s);      //   26   55:getstatic       #49  < Field PrintStream System.out>      //   27   58:aload_1               //   28   59:invokevirtual   #55  < Method void PrintStream.println(String)>      //   29   62:return                }  }

     

As you can see, although the compiler converts "+" into a StringBuilder class, the position of the StringBuilder object is inside the for statement. This means that every execution of a loop creates a StringBuilder object (in this example, 10 StringBuilder objects are created). Although Java has a garbage collector, however, this recycler may not work for a long time. If such garbage is generated continuously, a large amount of resources will be occupied. To solve this problem, you can directly use the StringBuilder class in the program to connect strings. The Code is as follows:

  1. package string;  import java.util.*;  public class TestStringBuilder  {      public static void main(String[] args)      {          String s = "";          Random rand = new Random();          StringBuilder result = new StringBuilder();          for (int i = 0; i <  10; i++)          {              result.append(rand.nextInt(1000));              result.append(" ");          }          System.out.println(result.toString());      }  }

     

The Decompilation result of the above Code is as follows:

  1. package string;  import java.io.PrintStream;  import java.util.Random;  public class TestStringBuilder  {      public TestStringBuilder()      {      //    0    0:aload_0               //    1    1:invokespecial   #8   < Method void Object()>      //    2    4:return                }      public static void main(String args[])      {          String s = "";      //    0    0:ldc1            #16  < String "">      //    1    2:astore_1                  Random rand = new Random();      //    2    3:new             #18  < Class Random>      //    3    6:dup                   //    4    7:invokespecial   #20  < Method void Random()>      //    5   10:astore_2                  StringBuilder result = new StringBuilder();      //    6   11:new             #21  < Class StringBuilder>      //    7   14:dup                   //    8   15:invokespecial   #23  < Method void StringBuilder()>      //    9   18:astore_3                  for(int i = 0; i <  10; i++)      //*  10   19:iconst_0              //*  11   20:istore          4      //*  12   22:goto            47          {              result.append(rand.nextInt(1000));      //   13   25:aload_3               //   14   26:aload_2               //   15   27:sipush          1000      //   16   30:invokevirtual   #24  < Method int Random.nextInt(int)>      //   17   33:invokevirtual   #28  < Method StringBuilder StringBuilder.append(int)>      //   18   36:pop                           result.append(" ");      //   19   37:aload_3               //   20   38:ldc1            #32  < String " ">      //   21   40:invokevirtual   #34  < Method StringBuilder StringBuilder.append(String)>      //   22   43:pop                       }      //   23   44:iinc            4  1      //   24   47:iload           4      //   25   49:bipush          10      //   26   51:icmplt          25          System.out.println(result.toString());      //   27   54:getstatic       #37  < Field PrintStream System.out>      //   28   57:aload_3               //   29   58:invokevirtual   #43  < Method String StringBuilder.toString()>      //   30   61:invokevirtual   #47  < Method void PrintStream.println(String)>      //   31   64:return                }  }

     

From The Decompilation results, we can see that the code for creating StringBuilder is placed out of the for statement. Although such processing looks complicated in the source program, it achieves higher efficiency and consumes less resources.

When using the StringBuilder class, be sure not to mix "+" and StringBuilder. Otherwise, more StringBuilder objects will be created, as shown in the following code:

  1. For (int I = 0; I <10; I ++) {result. append (rand. nextInt (1000); result. append ("") ;}to the following format: for (int I = 0; I <10; I ++) {result. append (rand. nextInt (1000) + "") ;}the decompilation result is as follows: for (int I = 0; I <10; I ++) // * 10 19: iconst_0 // * 11 20: istore 4 // * 12 22: goto 65 {result. append (new StringBuilder (String. valueOf (rand. nextInt (1000 )))). append (""). toString (); // 13 25: aload_3 // 14 26: new #21 <Class StringBuilder> // 15 29: dup

     

From the code above, we can see that the Java compiler has compiled "+" into the StringBuilder class, so that every cycle of the for statement creates a StringBuilder object.

If you compile the above Code under JDK1.4, you must change StringBuilder to StringBuffer, and JDK1.4 converts "+" to StringBuffer (because JDK1.4 does not provide the StringBuilder class ). The basic functions of StringBuffer and StringBuilder are the same, but StringBuffer is thread-safe, while StringBuilder is NOT thread-safe. Therefore, StringBuilder is more efficient.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.