版权声明:未经过博主同意,不得随意转发 https://blog.csdn.net/weixin_40918067/article/details/82257022
String类是不可变类,任何对String的改变都会引发新的String对象的生成;
StringBuffer是可变类,任何对它所指代的字符串的改变都不会产生新的对象,可变和不可变类这一对对象已经齐全了;
引入新的StringBuilder类???——》改变字符串内容时,采用StringBuffer能获得更好的性能,但是并不是最好的;
StringBuffer???——》线程安全
StringBuilder???——》非线程安全
【例子】String类为不可变类;
解析:
- 初始String值为“hello”,之后在这个字符串后面加上新的字符串“world”;
- 这个过程是需要重新在栈堆内存中开辟内存空间,才最终得到了“hello world”字符串,但同时也相应的需要开辟内存空间;
- 这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费;
- 为了应对经常性的字符串相关的操作,谷歌引入了两个新的类——StringBuffer类和StringBuilder类来对此中变化字符串进行处理;
那StringBuilder和StringBuffer的区别:
- HashTable是线程安全的,很多方法都是synchronized方法;
- HashMap不是线程安全的,但其在单线程程序中的性能比HashTable要高;
- StringBuffer和StringBuilder类的区别也在于此???——》就是支持线程同步保证线程安全而导致性能下降的问题;???——》StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高;
- 在大多数情况下建议使用StringBuilder类;但是在应用程序要求线程安全的情况下,则必须使用StringBuffer类;
三者的继承关系:
那么,接下来就用实例来证明:
package com.hct.test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @author: chengtai.he
* @created:2009-12-9 上午09:59:57
*/
public class StringBuilderTester {
private static final String base = " base string. ";
private static final int count = 2000000;
public static void stringTest() {
long begin, end;
begin = System.currentTimeMillis();
String test = new String(base);
for (int i = 0; i < count/100; i++) {
test = test + " add ";
}
end = System.currentTimeMillis();
System.out.println((end - begin)
+ " millis has elapsed when used String. ");
}
public static void stringBufferTest() {
long begin, end;
begin = System.currentTimeMillis();
StringBuffer test = new StringBuffer(base);
for (int i = 0; i < count; i++) {
test = test.append(" add ");
}
end = System.currentTimeMillis();
System.out.println((end - begin)
+ " millis has elapsed when used StringBuffer. ");
}
public static void stringBuilderTest() {
long begin, end;
begin = System.currentTimeMillis();
StringBuilder test = new StringBuilder(base);
for (int i = 0; i < count; i++) {
test = test.append(" add ");
}
end = System.currentTimeMillis();
System.out.println((end - begin)
+ " millis has elapsed when used StringBuilder. ");
}
public static String appendItemsToStringBuiler(List list) {
StringBuilder b = new StringBuilder();
for (Iterator i = list.iterator(); i.hasNext();) {
b.append(i.next()).append(" ");
}
return b.toString();
}
public static void addToStringBuilder() {
List list = new ArrayList();
list.add(" I ");
list.add(" play ");
list.add(" Bourgeois ");
list.add(" guitars ");
list.add(" and ");
list.add(" Huber ");
list.add(" banjos ");
System.out.println(StringBuilderTester.appendItemsToStirngBuffer(list));
}
public static String appendItemsToStirngBuffer(List list) {
StringBuffer b = new StringBuffer();
for (Iterator i = list.iterator(); i.hasNext();) {
b.append(i.next()).append(" ");
}
return b.toString();
}
public static void addToStringBuffer() {
List list = new ArrayList();
list.add(" I ");
list.add(" play ");
list.add(" Bourgeois ");
list.add(" guitars ");
list.add(" and ");
list.add(" Huber ");
list.add(" banjos ");
System.out.println(StringBuilderTester.appendItemsToStirngBuffer(list));
}
public static void main(String[] args) {
stringTest();
stringBufferTest();
stringBuilderTest();
addToStringBuffer();
addToStringBuilder();
}
}
上面的程序结果如下:
5266 millis has elapsed when used String.
375 millis has elapsed when used StringBuffer.
281 millis has elapsed when used StringBuilder.
I play Bourgeois guitars and Huber banjos
I play Bourgeois guitars and Huber banjos
解析:
- 从上面的结果来看,这三个类在单线程程序中的性能差别一目了然;
- 采用String对象时,即使运行次数仅是采用其他对象的1/100,但其执行时间仍然比其他对象高出25倍以上;
- 而采用StringBuffer对象和采用StringBuilder对象的差别也比较明显,前者是后者的1.5倍左右;
- 由此可见,如果我们的程序是在单线程下运行,或者是不必考虑到线程同步问题,我们应该优先使用StringBuilder类;
- 当然,如果要保证线程安全,自然非StringBuffer莫属了;
- 除了对多线程的支持不一样外,这两个类的使用几乎没有任何差别,上面的例子就是个很好的说明;
- appendItemsToStringBuiler和appendItemsToStirngBuffer两个方法除了采用的对象分别为StringBuilder和StringBuffer外,其他完全相同,而且效果也完全相同;
小结:
- 如果要操作少量的数据用 String;
- 多线程操作字符串缓冲区下操作大量数据 StringBuffer;
- 单线程操作字符串缓冲区下操作大量数据 StringBuilder;