在编写Java程序时,我们经常需要对某些字符串进行拼接,之前我们经常用“+”来拼接,但在Java中如果我们直接使用这种拼接方法,会建立很多String型的对象,这样一来,系统就会因为过多的String型对象而对服务器对象和系统性能造成很大的影响。所以,Java中有一种更好的拼接字符串的方法:使用StringBuffer或StringBuilder。
一、String和StringBuffer
◎ String :是不可变类,任何对String的改变都会产生新的String对象。
当我们使用String来拼接两个字符串时,我们可以执行下面的几行代码:
<span style="font-family:FangSong_GB2312;font-size:18px;">String a ="123"; String b = "456"; String c = a + b; </span>
这样拼接出来的字符串为:123456。而在程序执行完毕时,我们会发现为了满足程序执行的需要,系统在执行过程建立了a,b,c三个对象。也就是说,使用String的“+”方法来拼接字符串时,会产生很多String类型的新对象,用来满足程序调用和执行的需要。因此,当建立的对象过多,系统的性能和执行效率会因此而受到影响。
◎ StringBuffer:可变类,任何对它所指代的字符串的改变都不会产生新的对象。
使用StringBuffer执行两个字符串相加的操作过程:
<span style="font-family:FangSong_GB2312;font-size:18px;"> StringBuffer sb1 = new StringBuffer(str1); sb1.append(str2); String result1 = sb1.toString(); </span>
当这个过程执行完毕,我们所需要的内容只有result1这一个对象,而执行过程中间出现的sb1就已经是垃圾回收的目标了。这样不仅仅避免了执行过程中建立的多个String对象,而且降低了CPU的利用度。
此时,如果我们要实现sb1,sb2,sb3三个字符串的拼接,我们只需要在刚才的基础上,继续执行便可:
<span style="font-family:FangSong_GB2312;font-size:18px;">StringBuffer sb2 = new StringBuffer(result1); sb2.append(str3); String result2 = sb2.toString(); </span>
这样,对我们有用的就只有result2对象一个,其中生成的sb2和result1都已经成了系统回收的目标。如果继续增大字符串的数量,系统就会相应地产生若干个StringBuffer和String的垃圾对象。
而Java中的垃圾首先是占用内存的,然后Java的虚拟机会请垃圾回收的线程来回收这些垃圾,这样就又会出现CPU的损耗,同事这些垃圾对象生成的时候也会产生系统开销,所以如果在一个循环中使用字符串的“+”,导致的系统开销将是不可忽略和不可估量的。
但是相对于StringBuffer来进行字符串连接的话,
<span style="font-family:FangSong_GB2312;font-size:18px;">StringBuffer sb = new StringBuffer(); sb.append(str1); sb.append(str2); ..... sb.append(strN); String result = sb.toString(); </span>
除去中间的一个StringBuffer对象最后会被抛弃掉,其他的都是有效对象,比起上面产生的一对垃圾,提高的效率不是一星半点。
二、StringBuffer和StringBuilder
◎ StringBuffer
StringBuffer:字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。
StringBuffer 上的主要操作有append和insert方法。
◎ StringBuilder
StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder对象被当作是一个包含字符序列的变长数组。java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。
二者比较:
在大部分情况下,对执行速度而言,StringBuilder > StringBuffer。因为前者不需要考虑线程安全问题。
三、三兄弟的优缺点
String 类型和StringBuffer的主要性能区别:String是不可变的对象, 因此在每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。
使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。
在某些特别情况下, String 对象的字符串拼接其实是被 Java Compiler 编译成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,例如:
<span style="font-family:FangSong_GB2312;font-size:18px;">String s1 = “This is only a” + “ simple” + “ test”; StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”); </span>
生成 String s1对象的速度并不比 StringBuffer慢。其实在Java Compiler里,自动做了如下转换:
Java Compiler直接把上述第一条语句编译为:
<span style="font-family:FangSong_GB2312;font-size:18px;">String s1 = “This is only a simple test”; </span>
所以速度很快。但要注意的是,如果拼接的字符串来自另外的String对象的话,Java Compiler就不会自动转换了,速度也就没那么快了。
因此,如果要操作少量的数据,使用String;
单线程操作大量数据,使用StringBuilder;
多线程操作大量数据,使用StringBuffer。
原文:http://blog.csdn.net/ysc1123/article/details/45507849