String、StringBuffer、StringBuilder浅析

    在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是下面,主要是很多方法和重写父类方法时都加了同步锁。

@Override
public 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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值