String,StringBuffer与StringBuilder

  关于字符串的这三个类,在使用中频繁地接触到,现在对它们做一个总结。这三个类实现了接口CharSequence,而StringBuffer和StringBuilder还同时继承于AbstractStringBuilder这个父类。

 Java里的String类具体用法不具体说,现在主要讲一下String需要注意的一些问题。字符串常量池是String里的一个重要机制,通过字符串常量池,我们可以不用再为重复的字符串分配空间,有效地节省了资源。但是,如果不了解这个机制的话会导致很多的问题。例如:

         String A = "tajxrey";
		String B = "tajxrey";
		String C = new String("tajxrey");
		
		if (A == B)
		    System.out.println("A == B.");
		else
			System.out.println("A != B.");
		if (A.equals(B))
			System.out.println("A equals B.");
		else
			System.out.println("A doesn't equals B.");
		if (A == C)
			System.out.println("A == C");
		else
			System.out.println("A != C.");
		if(A.equals(C))
			System.out.println("A equals C.");
		else
			System.out.println("A doesn't equals C.");

  结果如下:

A == B.
A equals B.
A != C.
A equals C.

由上述结果可知,当初始化时是直接将值赋给String变量A,则A就会被放入常量池中。当有相同的值被直接赋给另一String变量B时,则是将A的地址赋给了B的地址,也就是说A和B指向的是同一地址。而通过new出来的C的地址是重新分配的。虽然C的值与A的相同,但是C的地址与A的却不一样。因此,在使用“==”比较的时候会出现不等的情况。在实际比较两String变量的值是否相等时,应该采用如下方法:

if (A != null && A.length != 0 && A.equals(B))
    System.out.println("A equals B.");    

   String类对于字符串处理的能力已经是十分的强大了,那为什么还会有StringBuffer和StringBuilder的出现?原因在于String的字符串拼接慢的令人发指。在String类相加的时候,首先会重新new一个StringBuffer进行append,然后再使用toString返回。一般来说StringBuffer和StringBuilder字符串拼接的速度是String万倍左右。

 

  StringBuffer和StringBuilder有太多相似之处,所以放在一起讲。相似的地方不说,StringBuffer与StringBuilder最大的不同在于StringBuffer线程安全,StringBuilder不安全。StringBuffer与StringBuilder相比拼接时间略慢,但是由于它是线程安全的,因此在多线程的时候使用的是StringBuffer。而StringBuilder只能在单线程的时候使用。引入programus的示例代码:

import java.util.Random;

public class Test {
    public static int demo(final Object stringJoiner, final int testCount) throws InterruptedException {
        ThreadGroup group = new ThreadGroup(stringJoiner.getClass().getName() + "@" + stringJoiner.hashCode()); 
        final Random rand = new Random(); 
        
        Runnable listAppender = new Runnable() {
            public void run() {
                try {
                    Thread.sleep(rand.nextInt(2));
                } catch (InterruptedException e) {
                    return; 
                } 
                if (stringJoiner instanceof StringBuffer) {
                    ((StringBuffer)stringJoiner).append("0");
                } else if (stringJoiner instanceof StringBuilder) {
                    ((StringBuilder)stringJoiner).append("0"); 
                }
            }
        }; 
        
        for (int i = 0; i < testCount; i++) {
            new Thread(group, listAppender, "InsertList-" + i).start(); 
        }
        
        while (group.activeCount() > 0) {
            Thread.sleep(10); 
        }
        
        return stringJoiner.toString().length(); 
    }
    
    public static void main(String[] args) throws InterruptedException {
        StringBuilder stringBuilder = new StringBuilder();
        StringBuffer stringBuffer = new StringBuffer();
        final int N = 10000; 
        for (int i = 0; i < 10; i++) {
            stringBuilder.delete(0, stringBuilder.length()); 
            stringBuffer.delete(0, stringBuffer.length()); 
            int builderLength = demo(stringBuilder, N); 
            int bufferLength = demo(stringBuffer, N); 
            System.out.println("StringBuilder/StringBuffer: " + builderLength + "/" + bufferLength); 
        }
    }
}

运行结果:

StringBuilder/StringBuffer: 9903/10000
StringBuilder/StringBuffer: 9930/10000
StringBuilder/StringBuffer: 9908/10000
StringBuilder/StringBuffer: 9944/10000
StringBuilder/StringBuffer: 9924/10000
StringBuilder/StringBuffer: 9910/10000
StringBuilder/StringBuffer: 9916/10000
StringBuilder/StringBuffer: 9926/10000
StringBuilder/StringBuffer: 9929/10000
StringBuilder/StringBuffer: 9916/10000

由上可知,StringBuilder由于线程不安全导致了一部分操作“丢失”。

  

posted @ 2014-02-13 15:06  viruseeee  阅读(312)  评论(0编辑  收藏  举报