您的位置:首页 > 产品设计 > UI/UE

Java StringBuffer和StringBuilder的区别

2016-12-06 10:19 489 查看

简介

之所以要使用StringBuffer或者StringBuilder是因为:

字符串本身是不可变的,而字符串拼接符“+”,实际上就相当于C++中的操作符重载函数,它的参数为2,因此在拼接次数较多的时候会产生大量的零时变量,并且不断地申请和释放资源,然后Java虚拟机会请出垃圾回收线程来回收这些垃圾,造成大量的时间和空间上的浪费。

而StringBuffer和StringBuilder均继承自AbstractStringBuilder,它的本质是使用char数组来进行缓存,只有当数组空间不足的时候才会重新申请空间,因此减少了申请和释放资源的次数,节约了时间。

区别

+(string,string) 用在单线程且拼接数较少的情况下

stringBuffer 用在多线程

stringBuilder 用在单线程

源码

通过源码可以看到:stringBuffer的append比起stringBuilder实质上就多了个同步而已。

StringBuffer.java

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
/**
* A cache of the last value returned by toString. Cleared
* whenever the StringBuffer is modified.
*/
private transient char[] toStringCache;
……
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
……
}


StringBuilder

public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
{
……
@Override
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
……
}


AbstractStringBuilder.java

abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;

/**
* The count is the number of characters used.
*/
int count;
……
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
……
}


测试用例

package com.demo.test;

public class StringBufferDemo {
private static final byte N_THREADS = 50;
private static final byte LOOP_COUNT = 50;
private static String str = "";

private static String testString() {
Thread[] runnables = new Thread[N_THREADS];
for (byte i = 0; i < N_THREADS; i++) {
runnables[i] = new Thread(new Runnable() {
@Override
public void run() {
for (byte i = 0; i < LOOP_COUNT; i++) {
str += "0";
}
}
});
}
for (Thread t : runnables) {
t.start();
}
for (Thread t : runnables) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return str;
}

private static String testStringBuffer() {
final StringBuffer stringBuffer = new StringBuffer();
Thread[] runnables = new Thread[N_THREADS];
for (byte i = 0; i < N_THREADS; i++) {
runnables[i] = new Thread(new Runnable() {
@Override
public void run() {
for (byte i = 0; i < LOOP_COUNT; i++) {
stringBuffer.append("0");
}
}
});
}
for (Thread t : runnables) {
t.start();
}
for (Thread t : runnables) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return stringBuffer.toString();
}

private static String testStringBuilder() {
final StringBuilder stringBuilder = new StringBuilder();
Thread[] runnables = new Thread[N_THREADS];
for (byte i = 0; i < N_THREADS; i++) {
runnables[i] = new Thread(new Runnable() {
@Override
public void run() {
for (byte i = 0; i < LOOP_COUNT; i++) {
stringBuilder.append("0");
}
}
});
}
for (Thread t : runnables) {
t.start();
}
for (Thread t : runnables) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return stringBuilder.toString();
}

public static void main(String[] args) throws InterruptedException {
long startTime, endTime;

System.out.println("string");
startTime = System.currentTimeMillis();
System.out.println(testString().length());
endTime = System.currentTimeMillis();
System.out.println("cost " + (endTime - startTime));

System.out.println("stringBuffer");
startTime = System.currentTimeMillis();
System.out.println(testStringBuffer().length());
endTime = System.currentTimeMillis();
System.out.println("cost " + (endTime - startTime));

System.out.println("stringBuilder");
startTime = System.currentTimeMillis();
System.out.println(testStringBuilder().length());
endTime = System.currentTimeMillis();
System.out.println("cost " + (endTime - startTime));
}
}


结果输出



string
2040
cost 13
stringBuffer
2500
cost 9
stringBuilder
2478
cost 7


参考 https://www.zhihu.com/question/20101840
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: