StringBuider

一、StringBuilder和"+"的区别

如果连接字符串行表达式很简单(如顺序结构),那么"+"和StringBuilder类基本是一样的,但如果结构比较复杂,如使用循环来连接字符串,那么产生的Java Byte Code就会有很大的区别。

因为在Java中无论使用何种方式进行字符串连接,实际上都使用的是StringBuilder类。

在源程序中使用了"+",在编译时仍然会将"+"转换成StringBuilder。

 

如果创建StringBuilder对象的位置在for语句内部,这就意味着每执行一次循环,就会创建一个StringBuilder对象,虽然Java有垃圾回收器,但这个回收器的工作时间是不定的。如果不断产生这样的垃圾,那么仍然会占用大量的资源(Eden内存会被大量吞噬)。解决这个问题的方法就是在程序中直接使用StringBuilder类来连接字符串。

 

简单的测试:

 

运行结果:

注意到调用了100000次Thread.sleep(1),减去100000ms就是实际运行的时间。

因此看出,10万次的str操作,用String消耗了将近400s,而用StringBuilder只消耗了1.5s

 

在使用StringBuilder类时要注意,不要"+"和StringBuilder混着用,否则会创建更多的StringBuilder对象。

StringBuffer和StringBuilder的功能基本一样,只是StringBuffer是线程安全的,而StringBuilder不是线程安全的。因此,StringBuilder的效率会更高。

 

二、StringBuilder的toString()方法

 

 

上述代码中,CPU会一直忙于进行内存的分配工作,会导致机器的load过高

用StringBuilder类中的length来判断是否有数值,这样就避免了无谓的内存操作。

 

每次调用toString方法,会重新new一个String出来。

 

在java.lang.String的代码中,看最后一行,value并不是直接指向的,而是通过系统拷贝函数进行的内存操作

 

那为啥会通过内存拷贝的形式来进行toString呢,原因在于StringBuilder内部有两个核心的属性,这两个记录了String中的内容,是字符数组的形式。

这时候对于字符数组操作,通过内存拷贝是最快的方式了。

 

 三、StringBuilder的capacity

StringBuilder默认的capacity是16个Byte,当我们append的内容超过16以后,它会自动扩容。因为这个扩容会导致复制,因此如果我们知道大概的大小,最好直接给出容量,这样免去很多复制操作,提高效率。

扩容方式:

1. 如果我们指定初始容量,比如StringBuilder str = new StringBuilder(20);那么之后每次扩容,都是以20为倍数;如果不指定,以16为倍数。

2. 使用默认str,如果append的内容超过16(但不超过32),那么增加一倍,str的capacity变成32;

3. 如果append的内容超过32,比如54,那么str的capacity直接为54;

4. 如果此时,再次append一些内容,总容量超过了32的倍数64,但是没有超过128,那么str的capacity为128;也就是它append后的容量必须超过当前容量(比如说54)的所对应的翻倍容量(比如16以下对应16,32以下16以上对应32,因此54对应64)的2倍后(也就是128),就按照append后的容量扩容,否则按照2倍递增的方式扩容。

 

 

posted on 2013-05-10 15:29  melburg  阅读(229)  评论(0)    收藏  举报