StringBuilder和StringBuffer的区别
1. String,StringBuilder和StringBuffer
String是final类,并且String对象一经创建就不可更改。值得注意的是final类不可被继承,因而String类创建出来的是静态的字符串常量。StringBuilder和StringBuffer是字符串变量。他们皆是继承自AbstractStringBuilder。
2. StringBuilder和StringBuffer的区别
1)同步
StringBuffer和String一样始自JDK1.0。StringBuffer中大部分方法都有synchronized关键字修饰,因而其是线程安全的。
例如:
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
StringBuilder是JDK1.5新增的,该类大部分方法没有关键字synchronized,其不是线程安全的。因为不用考虑同步,因而提高了操作的性能。同时,该类提供了一个与StringBuffer兼容的 API。
例如:
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
2)缓冲区
在toString方法上,StringBuffer每次获取字符串都会是直接用toStringCache来生成字符串而StringBuilder则每次都需要复制一次字符数组,然后再构造String。(通俗说就是如果字符串没有改变,多次使用toString时StringBuffer可以直接用缓存的toStringCache,而StringBuilder则无此设计)
//StringBuffer
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
//StringBuilder
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
3)性能
在性能上,对于少量的字符串操作,String不用新建类,因而方便使用。当需要处理的字符串操作很多时,字符串变量的类StringBuilder和StringBuffer会更有优势。
下面进行三个实验:
- 进行字符串"a"与"b"拼接并输出
- 进行字符串"1"到"100000"拼接并输出
- 在多线程下进行字符串大量操作时其实就只能使用StringBuffer了,因而此部分不做实验。
对于实验1:(取的是其中一个实验数据,多次实验结果一致)
CLASS | TASK | TIME |
---|---|---|
String | 输出“ab” | 5.561E-4 s |
StringBuilder | 输出“ab” | 2.09E-5 s |
StringBuffer | 输出“ab” | 8.6E-5 s |
对于实验2:(取的是其中一个实验数据,多次实验结果一致)
CLASS | TASK | TIME |
---|---|---|
String | 输出1到100000 | 17.6074861 s |
StringBuilder | 输出1到100000 | 0.0113411 s |
StringBuffer | 输出1到100000 | 0.0155818 s |
附上实验1与实验2的代码
public class StringSearch {
// 测试实验一操作所需要的时间,单位:秒
private static double test1(){
long startTime = System.nanoTime();
String s="a";
s=s+"b";
System.out.println(s);
long endTime = System.nanoTime();
return (endTime - startTime) / 1000000000.0;
}
private static double test2(){
long startTime = System.nanoTime();
StringBuffer s=new StringBuffer("a");
s.append("b");
System.out.println(s.toString());
long endTime = System.nanoTime();
return (endTime - startTime) / 1000000000.0;
}
private static double test3(){
long startTime = System.nanoTime();
StringBuilder s=new StringBuilder("a");
s.append("b");
System.out.println(s.toString());
long endTime = System.nanoTime();
return (endTime - startTime) / 1000000000.0;
}
public static void main(String[] args) {
double time1 = test1();
System.out.println("String, time: " + time1 + " s");
double time2 = test2();
System.out.println("StringBuffer, time: " + time2 + " s");
double time3 = test3();
System.out.println("StringBuilder, time: " + time3 + " s");
}
}
public class StringSearch {
// 测试实验二操作所需要的时间,单位:秒
private static double test1(){
long startTime = System.nanoTime();
String s="";
for(int i=1;i<=100000;i++)
s=s+i;
System.out.println(s);
long endTime = System.nanoTime();
return (endTime - startTime) / 1000000000.0;
}
private static double test2(){
long startTime = System.nanoTime();
StringBuffer s=new StringBuffer();
for(int i=1;i<=100000;i++)
s=s.append(i);
System.out.println(s.toString());
long endTime = System.nanoTime();
return (endTime - startTime) / 1000000000.0;
}
private static double test3(){
long startTime = System.nanoTime();
StringBuilder s=new StringBuilder();
for(int i=1;i<=100000;i++)
s=s.append(i);
System.out.println(s.toString());
long endTime = System.nanoTime();
return (endTime - startTime) / 1000000000.0;
}
public static void main(String[] args) {
double time1 = test1();
System.out.println("String, time: " + time1 + " s");
double time2 = test2();
System.out.println("StringBuffer, time: " + time2 + " s");
double time3 = test3();
System.out.println("StringBuilder, time: " + time3 + " s");
}
}
参考资料:
https://blog.csdn.net/qushaming/article/details/82971901
https://blog.csdn.net/youanyyou/article/details/86504755