String StringBuilder以及StringBuffer

例一:[看了威哥视频,下面更好理解]

package sunjava;
public class String_test {     
    public static void main(String[] args) { 
        String str1 = "hello world"; 
        String str2 = new String("hello world"); 
        String str3 = "hello world"; 
        String str4 = new String("hello world"); 
          
        System.out.println(str1==str2); 
        System.out.println(str1==str3); 
        System.out.println(str2==str4); 
    } 
} 

结果:

false
true
false

--------------

总结: 

一、String str1 = "hello world";和String str3 = "hello world"; 都在编译期间生成了 字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池(当然只保存了一份)。通过这种方式来将String对象跟引用绑定的话,JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量,如果存在,则直接将引用指向已经存在的字面常量;否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。

二、通过new关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过new来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。

例二:

package sunjava;
public class String_test {     
    public static void main(String[] args) { 
        String string = ""; 
        for(int i=0;i<10000;i++){ 
            string += "hello"; 
        } 
    } 
} 

上面new出了10000个对象,修改方案如下

public class Main { 
          
    public static void main(String[] args) { 
        StringBuilder stringBuilder = new StringBuilder(); 
        for(int i=0;i<10000;i++){ 
            stringBuilder.append("hello"); 
        } 
    } 
} 

上面new操作只进行了一次,也就是说只生成了一个对象

 继续优化

用StringBuffer是线程安全的。

 二、测试案例

public class String_test { 
    private static int time = 50000; 
    public static void main(String[] args) { 
        testString(); 
        testStringBuffer(); 
        testStringBuilder(); 
        test1String(); 
        test2String(); 
    }    
      
    public static void testString () { 
        String s=""; 
        long begin = System.currentTimeMillis();  
        for(int i=0; i<time; i++){  
            s += "java";  
        }  
        long over = System.currentTimeMillis();  
        System.out.println("操作"+s.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");  
    } 
      
    public static void testStringBuffer () { 
        StringBuffer sb = new StringBuffer(); 
        long begin = System.currentTimeMillis();  
        for(int i=0; i<time; i++){  
            sb.append("java");  
        }  
        long over = System.currentTimeMillis();  
        System.out.println("操作"+sb.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");  
    } 
      
    public static void testStringBuilder () { 
        StringBuilder sb = new StringBuilder(); 
        long begin = System.currentTimeMillis();  
        for(int i=0; i<time; i++){  
            sb.append("java");  
        }  
        long over = System.currentTimeMillis();  
        System.out.println("操作"+sb.getClass().getName()+"类型使用的时间为:"+(over-begin)+"毫秒");  
    } 
      
    public static void test1String () { 
        long begin = System.currentTimeMillis();  
        for(int i=0; i<time; i++){  
            String s = "I"+"love"+"java";  
        }  
        long over = System.currentTimeMillis();  
        System.out.println("字符串直接相加操作:"+(over-begin)+"毫秒");  
    } 
      
    public static void test2String () { 
        String s1 ="I"; 
        String s2 = "love"; 
        String s3 = "java"; 
        long begin = System.currentTimeMillis();  
        for(int i=0; i<time; i++){  
            String s = s1+s2+s3;  
        }  
        long over = System.currentTimeMillis();  
        System.out.println("字符串间接相加操作:"+(over-begin)+"毫秒");  
    } 
      
} 

 结果:

操作java.lang.String类型使用的时间为:4485毫秒
操作java.lang.StringBuffer类型使用的时间为:8毫秒
操作java.lang.StringBuilder类型使用的时间为:3毫秒
字符串直接相加操作:2毫秒
字符串间接相加操作:17毫秒

----------------

总结:

String、StringBuilder、StringBuffer三者的执行效率:

  StringBuilder > StringBuffer > String

  当然这个是相对的,不一定在所有情况下都是这样。

当字符串相加操作或者改动较少的情况下,建议使用 String str="hello"这种形式;

  当字符串相加操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。

参考文章:http://www.cnblogs.com/dolphin0520/p/3778589.html

原文地址:https://www.cnblogs.com/bluewelkin/p/4059107.html