二十四桥仍在,波心荡、冷月无声。
——姜夔《扬州慢》
## Java基础之StringBuffer和StringBuilder
1. 前言-浅谈String:
- String 类中使用 final 关键字修饰字符数组来保存字符串, private final char value[] ,所以String 对象是不可变的。
- String 中的对象是不可变的,也就可以理解为常量,线程安全。
- 每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象。
- String类传送门…
2. 可变的StringBuffer和StringBuilder
- StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在AbstractStringBuilder 中也是使用字符数组保存字符串 char[] value 但是没有用 final 关键字修饰,所以这两种对象都是可变的。
- StringBuilder 与 StringBuffer 的构造方法都是调用父类构造方法也就是 AbstractStringBuilder 实现的,大家可以看下面的源码分析。
3. 线程安全性
AbstractStringBuilder 是 StringBuilder 与StringBuffer 的公共父类,定义了一些字符串的基本操作,如 append、insert、indexOf 等公共方法。
- StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
- StringBuilder 并没有对方法进行加同步锁,所以是线程不安全的。
4. 性能
StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。
相同情况下使用StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
5. AbstractStringBuilder部分源码
可变的字符序列
–基于JDK1.8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
abstract class AbstractStringBuilder implements Appendable, CharSequence { char[] value; int count; AbstractStringBuilder() { } AbstractStringBuilder(int capacity) { value = new char[capacity]; } }
|
5.1 StringBuffer部分源码
注意StringBuffer中方法中的synchronized锁
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence{
private transient char[] toStringCache; static final long serialVersionUID = 3388685877147921107L;
public StringBuffer() { super(16); }
public StringBuffer(int capacity) { super(capacity); }
public StringBuffer(String str) { super(str.length() + 16); append(str); }
public StringBuffer(CharSequence seq) { this(seq.length() + 16); append(seq); }
@Override public synchronized int length() { return count; }
@Override public synchronized int capacity() { return value.length; }
@Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; }
@Override public synchronized StringBuffer insert( int index, char[] str, int offset,int len ){ toStringCache = null; super.insert(index, str, offset, len); return this; } }
|
对length()和capacity()
两个方法以及默认构造器的测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static void main(String[] args) { StringBuffer stringBuffer = new StringBuffer(); stringBuffer.append("dd"); stringBuffer.append("ai"); stringBuffer.append("mm");
System.out.println("stringBuffer.length() = " + stringBuffer.length()); System.out.println("stringBuffer.capacity() = " + stringBuffer.capacity()); }
|
一系列的重载方法:
5.2 StringBuilder部分源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence {
static final long serialVersionUID = 4383685877147921099L; public StringBuilder() { super(16); } public StringBuilder(int capacity) { super(capacity); }
public StringBuilder(String str) { super(str.length() + 16); append(str); }
@Override public StringBuilder append(String str) { super.append(str); return this; } public StringBuilder append(StringBuffer sb) { super.append(sb); return this; } @Override public StringBuilder insert( int index, char[] str, int offset,int len ){ super.insert(index, str, offset, len); return this; } }
|
6. 小结:
- 操作少量的数据: 适用String
- 单线程操作字符串缓冲区下操作大量数据: 适用StringBuilder
- 多线程操作字符串缓冲区下操作大量数据: 适用StringBuffer