目录
(一)为什么要引入StringBuilder和StringBuffer
(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源码
java
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源码
java
private void ensureCapacityInternal(int minimumCapacity) {//所需最小数组大小
// overflow-conscious code
if (minimumCapacity - value.length > 0) {如果所需最小数组大于当前数组
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));//调用newCapacity方法扩容并将原数组copy到新数组
}
}
2.3 调用newCapacity
方法计算新的容量。新的容量是当前容量的两倍加2(即2n+2
,其中n是当前容量),如果计算出的新容量仍然小于最小所需容量,则将新容量设置为最小所需容量
newCapacity源码
java
private int newCapacity(int minCapacity) {//传入所需最小数组大小
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;//将当前数组×2+2
if (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 的操作是同步的,从而保证了线程安全,但也牺牲了效率
(4)StringBuilder和StringBuffer常用方法
绿色为返回值类型,StringBuffer返回类型可替换为StringBuilder类型
StringBuff append(String str) :在尾部追加,相当于String 的 += ,可以追加: boolean 、 char 、 char[], double、 float 、 int 、 long 、 Object 、 String 、 StringBuff 的变量
char charAt(int index) :获取index 位置的字符
int length():获取字符串的长度
int capacity():获取底层保存字符串空间总的大小
void ensureCapacity(int mininmumCapacity) :扩容
void setCharAt(int index, char ch) :将index 位置的字符设置为 ch
int indexOf(String str) :返回str 第一次出现的位置
int indexOf(String str, int fromIndex):从fromIndex 位置开始查找 str 第一次出现的位置
int lastIndexOf(String str):返回最后一次出现str 的位置
int lastIndexOf(String str, int fromIndex) :从fromIndex 位置开始找 str 最后一次出现的位置
StringBuff insert(int offset, String str) :在offset 位置插入:八种基类类型 & String 类型 & Object 类型数据
StringBuffe r deleteCharAt(int index) :删除index 位置字符
StringBuffer delete(int start, int end) :删除[start, end) 区间内的字符
StringBuffer replace(int start, int end, String str) :将[start, end) 位置的字符替换为 str
String substring(int start) :从start 开始一直到末尾的字符以 String 的方式返回
String substring(int start, int end):将[start, end) 范围内的字符以 String 的方式返回
StringBuffer reverse() :反转字符串
String toString() :将所有字符按照String 的方式返回
(三)总结
1.String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
2.StringBuffer与StringBuilder大部分功能是相似的
3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作,因此在多线程环境下使用StringBuffer,在单线程环境下为提升效率,可以使用StringBuilder。