目录
(一)为什么要引入StringBuilder和StringBuffer
(二)StringBuilder和StringBuffer
(1)底层数组长度
(2)StringBuilder与StringBuffer扩容机制
(3)StringBuilder和StringBuffer区别
(三)总结
(一)为什么要引入StringBuilder和StringBuffer
上一个文章我们已经了解了String类——>String类
String的不可变性意味着一旦创建了String对象,就不能更改其内容。如果需要修改字符串,就必须创建一个新的String对象。这种特性在需要频繁修改字符串的场景下会导致大量的临时对象被创建,可能会导致更高的内存使用,从而增加垃圾回收的负担,并可能影响性能.
而StringBuilder和StringBuffer底层维护的是一个可变的数组,当遇到需要频繁修改字符串的场景下能够大量减少临时对象的创建,提升性能。
(二)StringBuilder和StringBuffer
(1)底层数组长度
StringBuilder和StringBuffer的底层数组默认长度是16
如下图为StringBuilder源码中,若创建StringBuilder时没传入参数,那么会默认创建一个大小为16的数组
若传入了参数,创建数组的大小=当前参数值的长+16
如下图为StringBuilder源码中,若创建StringBuilder时传入参数,那么会默认创建一个大小为当前参数值长(str.length())+ 16的数组
(2)StringBuilder与StringBuffer扩容机制
2.1在append
方法内部,会调用ensureCapacityInternal
方法,该方法会检查当前容量是否足够。
append源码
public AbstractStringBuilder append(char[] str) {int len = str.length;ensureCapacityInternal(count + len);//调用此方法判断数组是否需要扩容System.arraycopy(str, 0, value, count, len);count += len;return this;}
2.2 如果当前容量不足以存储新的字符(即最小所需容量大于当前容量),则需要扩容
ensureCapacityInternal源码
private void ensureCapacityInternal(int minimumCapacity) {//所需最小数组大小// overflow-conscious codeif (minimumCapacity - value.length > 0) {如果所需最小数组大于当前数组value = Arrays.copyOf(value,newCapacity(minimumCapacity));//调用newCapacity方法扩容并将原数组copy到新数组}}
2.3 调用newCapacity
方法计算新的容量。新的容量是当前容量的两倍加2(即2n+2
,其中n是当前容量),如果计算出的新容量仍然小于最小所需容量,则将新容量设置为最小所需容量
newCapacity源码
private int newCapacity(int minCapacity) {//传入所需最小数组大小// overflow-conscious codeint newCapacity = (value.length << 1) + 2;//将当前数组×2+2if (newCapacity - minCapacity < 0) {//如果扩容过后还小于所需最小数组大小newCapacity = minCapacity;//直接等于所需最小数组大小}return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)? hugeCapacity(minCapacity): newCapacity;}
(3)StringBuilder和StringBuffer区别
StringBuilder:线程不安全。StringBuilder 的方法没有被 synchronized 修饰,因此它不能同步访问,多个线程同时操作同一个 StringBuilder 实例可能会导致数据不一致的问题,但效率有所提升。
StringBuffer:线程安全。StringBuffer 的所有公开方法都被 synchronized 修饰,这意味着在多线程环境中,对 StringBuffer 的操作是同步的,从而保证了线程安全,但也牺牲了效率
(三)总结
1.String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
2.StringBuffer与StringBuilder大部分功能是相似的
3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作,因此在多线程环境下使用StringBuffer,在单线程环境下为提升效率,可以使用StringBuilder。