zoukankan      html  css  js  c++  java
  • string,stringbuffer,stringbuilder区别?

    String:

      1,是字符串常量,一旦创建就不能修改。对于已经存在了的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去。

      2,String也是final类,不能被继承。

      3,而且String是对象而不是基本类型。

      4,string覆盖了equals方法和hashCode()方法。

    StingBuffer:

      1,是字符串可变对象,可以对字符串进行操作,修改字符串原有值时不会新建一个对象。

      2,执行效率较慢,但是线程安全

      3,StringBuffer没有覆盖equals方法和hashCode()方法。

      4,可以动态的构造字符数据,append()方法。

    StringBuilder:

      1,也是字符串可变对象,同StringBuffer一样,可以对字符串进行操作,也不会新建对象。

      2,执行效率高效,但是线程不安全。

    Java中测试StringBuilder、StringBuffer、String在字符串拼接上的性能

    应一个大量字符串拼接的任务

    测试一下StringBuilder、StringBuffer、String在操作字符串拼接时候的性能

    性能上理论是StringBuilder  >  StringBuffer  >  String

    测试方法:

    创建一个StirngTest类含有静态常量字符串是26个字母,以及一个循环轮数

    在测试时采用循环来操作字符串的拼接,计算操作时间并输出:

    package com.test.xlc;
    
    import java.util.Random;
    
    public class StringTest {
        
        static final String strFinal = "abcdefghijklmnopqrstovwxyz";
        static final int forInt = 100;
        
        static void StringBuilderTest() {
            
            Random rand = new Random(47);
            StringBuilder strB = new StringBuilder();
            long start = System.currentTimeMillis();
            for(int i = 0; i < forInt; ++i) {
                int randInt = rand.nextInt(23);
                strB.append(strFinal.substring(randInt, randInt + 4));
            }
            long end = System.currentTimeMillis();
    //        System.out.println(strB.toString());
            System.out.println("StringBuilderTest:" + (end - start));
        }
        
        static void StringBufferTest() {
            Random rand = new Random(47);
            StringBuffer strB = new StringBuffer();
            long start = System.currentTimeMillis();
            for(int i = 0; i < forInt; ++i) {
                int randInt = rand.nextInt(23);
                strB.append(strFinal.substring(randInt, randInt + 4));
            }
            long end = System.currentTimeMillis();
    //        System.out.println(strB.toString());
            System.out.println("StringBufferTest:" + (end - start));
        }
        
        static void StringOnly() {
            Random rand = new Random(47);
            String str = "";
            long start = System.currentTimeMillis();
            for(int i = 0; i < forInt; ++i) {
                int randInt = rand.nextInt(23);
                str += strFinal.substring(randInt, randInt + 4);
            }
            long end = System.currentTimeMillis();
    //        System.out.println(str);
            System.out.println("String:" + (end - start));
        }
        
        
        public static void main(String...args) {
            StringBuilderTest();
            StringBufferTest();
            StringOnly();
            
        }
    }

    测试循环次数:

    100

    StringBuilderTest:0
    StringBufferTest:0
    String:0

    1000

    StringBuilderTest:1
    StringBufferTest:0
    String:7

    10000

    StringBuilderTest:2
    StringBufferTest:2
    String:217

    100000

    StringBuilderTest:12
    StringBufferTest:10
    String:17136

    1000000

    StringBuilderTest:55
    StringBufferTest:53
    我提前终止了

    之后我又测试了拼接长串,本实验结果显示在拼接字符串的效率上:

    StringBuffer  >    StringBuilder  >  String

    java中StringBuilder与加号拼接字符串的效率分析

    java version "1.8.0_191"
    Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
    Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

    案例1:拼接字符串常量

     String s1 = "a" + "b" + "c";
        String s2 = new StringBuilder().append("a").append("b").append("c").toString();

    反编译class文件

      String s1 = "abc";
        String s2 = "a" + "b" + "c";

    Byte Code

     0  ldc <String "abc"> [21]
         2  astore_1 [s1]
         3  new java.lang.StringBuilder [23]
         6  dup
         7  invokespecial java.lang.StringBuilder() [25]
        10  ldc <String "a"> [26]
        12  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [28]
        15  ldc <String "b"> [32]
        17  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [28]
        20  ldc <String "c"> [34]
        22  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [28]
        25  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [36]
        28  astore_2 [s2]

    分析:

        可以看出,使用 加号 进行字符串常量的拼接在编译时就已经完成,而使用 StringBuilder 进行字符串拼接需要在运行时完成。所以单纯的字符串常量拼接 加号 的效率 应该高于 StringBuilder,下面我们进行测试:

    long l1 = System.currentTimeMillis();
        for (int i=0; i<1_000_000; i++) {
            String s1 = "a" + "b" + "c";
        }
        System.out.println(System.currentTimeMillis() - l1);    //结果: 2
        
        long l2 = System.currentTimeMillis();
        for (int i=0; i<1_000_000; i++) {
            String s2 = new StringBuilder().append("a").append("b").append("c").toString();
        }
        System.out.println(System.currentTimeMillis() - l2);    //结果 : 19

     测试结果与预测一致。

    案例2:拼接字符串与引用

     String s1 = "a";
        String s2 = new StringBuilder().append(s1).append("b").append("c").toString();
        String s3 = s1 + "b" + "c";

    反编译class文件

     String t1 = "a";
        String t2 = t1 + "b" + "c";
        String t3 = t1 + "bc";

    Byte Code

    L1
        LINENUMBER 6 L1
        NEW java/lang/StringBuilder
        DUP
        INVOKESPECIAL java/lang/StringBuilder.<init> ()V
        ALOAD 1
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        LDC "b"
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        LDC "c"
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
        ASTORE 2
       L2
        LINENUMBER 7 L2
        NEW java/lang/StringBuilder
        DUP
        INVOKESPECIAL java/lang/StringBuilder.<init> ()V
        ALOAD 1
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        LDC "bc"
        INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
        INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
        ASTORE 3
    L3

    分析:

        从反编译的结果可以看出加号拼接的方式在编译过程中完成了"b"、"c"的拼接,而创建 StringBuilder 对象进行拼接需要在运行中进行"b"、"c"的拼接,加号拼接的方式应该更高效,下面是测试结果:

    String s1 = "a";
    long l1 = System.currentTimeMillis();
    for (int i=0; i<1_000_000; i++) {
    String s2 = new StringBuilder().append(s1).append("b").append("c").toString();
    }
    System.out.println(System.currentTimeMillis() - l1); //结果: 66
    
    long l2 = System.currentTimeMillis();
    for (int i=0; i<1_000_000; i++) {
    String s3 = s1 + "b" + "c";
    }
    System.out.println(System.currentTimeMillis() - l2);//结果 : 41

    测试结果与预期一致。

    案例3:循环拼接字符串

        通常我们都会对一个对象进行字符串的循环拼接,例如:

    String s1 = "";
        long l1 = System.currentTimeMillis();
        for(int i=0; i<100_000; i++) {
            s1 = s1 + "a" + "b" + "c" + "d" + "e" + "f";
        }
        System.out.println((System.currentTimeMillis() - l1) + " " + s1.length());  //结果 15041 600000
        
        StringBuilder sb = new StringBuilder();
        String s2;
        long l2 = System.currentTimeMillis();
        for(int i=0; i<100_000; i++) {
            sb.append("a").append("b").append("c").append("d").append("e").append("f");
        }
        s2 = sb.toString();
        System.out.println((System.currentTimeMillis() - l2) + " " + s2.length());  //结果 6 600000

    反编译classes

    String s1 = "";
        long l1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
          s1 = s1 + "a" + "b" + "c" + "d" + "e" + "f";
        }
        System.out.println(System.currentTimeMillis() - l1 + " " + s1.length());
        
        StringBuilder sb = new StringBuilder();
        
        long l2 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
          sb.append("a").append("b").append("c").append("d").append("e").append("f");
        }
        String s2 = sb.toString();
        System.out.println(System.currentTimeMillis() - l2 + " " + s2.length());

    Byte Code

     0  ldc <String ""> [16]
          2  astore_1 [s1]
          3  invokestatic java.lang.System.currentTimeMillis() : long [18]
          6  lstore_2 [l1]
          7  iconst_0
          8  istore 4 [i]
         10  goto 61
         13  new java.lang.StringBuilder [24]
         16  dup
         17  aload_1 [s1]
         18  invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [26]
         21  invokespecial java.lang.StringBuilder(java.lang.String) [32]
         24  ldc <String "a"> [35]
         26  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
         29  ldc <String "b"> [41]
         31  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
         34  ldc <String "c"> [43]
         36  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
         39  ldc <String "d"> [45]
         41  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
         44  ldc <String "e"> [47]
         46  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
         49  ldc <String "f"> [49]
         51  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
         54  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [51]
         57  astore_1 [s1]
         58  iinc 4 1 [i]
         61  iload 4 [i]
         63  ldc <Integer 100000> [55]
         65  if_icmplt 13
         68  getstatic java.lang.System.out : java.io.PrintStream [56]
         71  new java.lang.StringBuilder [24]
         74  dup
         75  invokestatic java.lang.System.currentTimeMillis() : long [18]
         78  lload_2 [l1]
         79  lsub
         80  invokestatic java.lang.String.valueOf(long) : java.lang.String [60]
         83  invokespecial java.lang.StringBuilder(java.lang.String) [32]
         86  ldc <String " "> [63]
         88  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
         91  aload_1 [s1]
         92  invokevirtual java.lang.String.length() : int [65]
         95  invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [69]
         98  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [51]
        101  invokevirtual java.io.PrintStream.println(java.lang.String) : void [72]
        104  new java.lang.StringBuilder [24]
        107  dup
        108  invokespecial java.lang.StringBuilder() [77]
        111  astore 4 [sb]
        113  invokestatic java.lang.System.currentTimeMillis() : long [18]
        116  lstore 6 [l2]
        118  iconst_0
        119  istore 8 [i]
        121  goto 160
        124  aload 4 [sb]
        126  ldc <String "a"> [35]
        128  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
        131  ldc <String "b"> [41]
        133  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
        136  ldc <String "c"> [43]
        138  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
        141  ldc <String "d"> [45]
        143  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
        146  ldc <String "e"> [47]
        148  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
        151  ldc <String "f"> [49]
        153  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
        156  pop
        157  iinc 8 1 [i]
        160  iload 8 [i]
        162  ldc <Integer 100000> [55]
        164  if_icmplt 124
        167  aload 4 [sb]
        169  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [51]
        172  astore 5 [s2]
        174  getstatic java.lang.System.out : java.io.PrintStream [56]
        177  new java.lang.StringBuilder [24]
        180  dup
        181  invokestatic java.lang.System.currentTimeMillis() : long [18]
        184  lload 6 [l2]
        186  lsub
        187  invokestatic java.lang.String.valueOf(long) : java.lang.String [60]
        190  invokespecial java.lang.StringBuilder(java.lang.String) [32]
        193  ldc <String " "> [63]
        195  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [37]
        198  aload 5 [s2]
        200  invokevirtual java.lang.String.length() : int [65]
        203  invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [69]
        206  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [51]
        209  invokevirtual java.io.PrintStream.println(java.lang.String) : void [72]

    析:

        测试结果 StringBuilder拼接字符串 的效率 远远高于 加号拼接字符串,主要原因在于 加号拼接字符串的方式 每次循环开始时都会创建一个 StringBuilder实例(Byte Code 65行与13行 ps: if_icmplt 条件分支指令 如果一个int类型值小于另外一个int类型值,则跳转),而 StringBuilder拼接字符串 的方式只在循环开始前创建了一个 StringBuilder实例。



  • 相关阅读:
    算法导论 第二部分——排序和顺序统计量
    算法导论——第一部分——基础知识
    liunx中的进程与线程
    vector中pair的排序方法
    sql 入门经典(第五版) Ryan Stephens 学习笔记 第五部分: 性能调整
    sql 入门经典(第五版) Ryan Stephens 学习笔记  第四部分:建立复杂的数据库查询/
    Object C学习笔记1-基本数据类型说明
    Objective-C(生命周期)
    从 React 的组件更新谈 Immutable 的应用
    React性能优化总结(转)
  • 原文地址:https://www.cnblogs.com/qingmuchuanqi48/p/11941640.html
Copyright © 2011-2022 走看看