String StringBuffer StringBuilder区别浅析

来源:互联网 发布:oracle sql参考手册 编辑:程序博客网 时间:2024/05/21 17:21

在Java中,我们操作最多的类应该就是String了,String类提供了很多字符串操作的方法,其实功能上所有操作都能用String解决,那么我们为什么还要有StringBuffer和StringBuilder呢?是性能好吗?好多少呢?以及为什么好呢?

   首先我们来看String的生成“abc”的三个代码,我们知道Stirng的==判断的是地址,大家猜下结果。

String a = new String("abc");String b = "abc";String c = "ab"+"c";System.out.println(a == b);System.out.println(a == c);System.out.println(b == c);
  结果是false、false、true.这是因为“ab”+“c”会先编译成"abc",而且相信你听过在内存中有块专门存储String的区域,当相同时会直接把引用给c。但是a就不一样了,new的时候会先开辟一个对象的堆内存。而且编辑工具很可能会提醒你new是没意义的。那你可能会说我就想要一个特殊的堆地址不行吗,然后我的String就在这个堆里了。其实不行的,会换堆。我们来看看String类。

/** The value is used for character storage. */private final char value[];
  可以看出String存在一个char数组中,而数组我们都知道是定长的。当长度改变时我们得到的一定是另一个数组了,而且由于是final,也就是说一个String对象只能有一个char数组。要变长就得另一个String对象,也就是另一个堆了。那么我们不能不用final吗。当然可以,所以当长度改变的时候就有了StringBuffer和StringBuilder了。他们继承的都是AbstractStringBuilder,在JDK1.5加入的。

/** * The value is used for character storage.
 */
char[] value;
.....
value = Arrays.copyOf(value, newCapacity);
....
  可以看到不是final了,而且新的数组生成用的是Arrays,copyOf方法。那么StringBuffer和StringBuilder的区别是什么呢。很多人可能已经知道了是线程安全不安全。如下StringBuilder是

public StringBuilder delete(int start, int end) {    delete0(start, end);    return this;}
  StringBuffer是下面,主要是很多方法和重写父类方法时都加了同步锁。

@Overridepublic synchronized void trimToSize() {    super.trimToSize();}
public synchronized StringBuffer delete(int start, int end) {    delete0(start, end);    return this;}
那么最后性能呢,我们来写个小程序测试下.

public static void main(String[] args) {    long time = System.currentTimeMillis();    StringBuilder a = new StringBuilder("");    for (int i = 0; i < 100000; i++) {        a.append("1");    }    System.out.println(time-System.currentTimeMillis());    time = System.currentTimeMillis();    StringBuffer b = new StringBuffer("");    for (int i = 0; i < 100000; i++) {        b.append("1");    }    System.out.println(time-System.currentTimeMillis());    time = System.currentTimeMillis();    String c = "";    for (int i = 0; i < 100000; i++) {        c = c +"1";    }    System.out.println(time-System.currentTimeMillis());}
输出结果是

-4
-2
-1642

这里-1642容易理解,创建对象和对象重复判断的花销很大。问题是StringBuffer怎么比StringBuilder还快了,这是因为StringBuilder在前面,main程序刚启动肯定慢,当数值再大些就看出差异了,如果再用多线程差异更大些。

结论是当我们要的字符串常改变长度时用StringBuffer和StringBuilder,而当没有同步问题时我们用StringBuilder。

1 0