JAVA中的StringBuilder和StringBufferString的扩容机制
StringBuilder 和 StringBuffer
StringBuilder 和 StringBuffer 是 Java 中用于可变字符串操作的类,它们都继承自 AbstractStringBuilder。它们的主要区别在于 StringBuffer 的方法是同步的,而 StringBuilder 的方法不是,因此 StringBuilder 在单线程环境下效率更高。在扩容机制上,StringBuilder 和 StringBuffer 基本上是一致的。
提示:以下是本篇文章正文内容,下面案例可供参考
源码分析
StringBuilder 和 StringBuffer 都继承自AbstractStringBuilder,StringBuilder 和 StringBuffer 的扩容机制是一样的,因此分析一个即可。
* @see java.lang.String
* @since 1.5
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
* @see java.lang.String
* @since JDK1.0
* public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
接下来看一下String Builder底层的一些方法。
1.StringBuilder的无参构造方法
StringBuilder的无参构造初始容量为:16,下图为无参构造方法的源码
它调用了父类的有参构造方法。
/**
* Constructs a string builder with no characters in it and an
* initial capacity of 16 characters.
*/
public StringBuilder() {
super(16);
}
下图为父类的有参构造方法,此时父类构造方法中的int capacity参数为16,也就是它的初始容量。value为它的成员变量,对成员变量进行了初始化操作,value底层为char类型的数组,没有被final修饰,可以改变指向。
/**
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
2.StringBuilder的有参构造方法
有参构造分两种:
下图为第一种有参构造方法,参数为int值,可以根据需要指定数组的初始化容量。设置int capacity的数值。
public StringBuilder(int capacity) {
super(capacity);
}
第二种有参构造方法,其中参数为字符串类型。它调用了父类的有参构造方法,里面的参数为字符串的长度+初始长度16。接着调用了append方法,
进入append方法,又调用父类的append方法,返回值为字符串类型。
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
有参和无参扩容方法都一样的。都是从当前容量开始扩容。一次追加长度超过当前容量,则会按照当前容量2+2 扩容一次。一次追加长度不仅超过初始容量,而且按照当前容量2+2 扩容一次也不够,其容量会直接扩容到与所添加的字符串长度相等的长度。之后再追加的话,还会按照当前容量*2+2进行扩容。
private int newCapacity(int minCapacity) {
// overflow-conscious code
int newCapacity = (value.length << 1) + 2;
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
? hugeCapacity(minCapacity)
: newCapacity;
}
private int hugeCapacity(int minCapacity) {
if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
throw new OutOfMemoryError();
}
return (minCapacity > MAX_ARRAY_SIZE)
? minCapacity : MAX_ARRAY_SIZE;
}
代码示例
1、一次添加的长度不超过16不会进行扩容
public class Test01 {
public static void main(String[] args) {
//无参构造初始容量为: 16
StringBuilder a = new StringBuilder();
a.append("abc");
a.append("799898989");
System.out.println(a);
//使用StringBuilder的capacity()方法可以查看其当前容量
System.out.println("a的容量为:"+a.capacity()+" a的长度为:"+a.length());
}
}
此时输出结果为
2、一次追加字符串的长度超过了16,其容量会按照:当前容量2+2 进行扩容,即:162+2=34
public class Test01 {
public static void main(String[] args) {
//无参构造初始容量为: 16
StringBuilder a = new StringBuilder();
a.append("abc");
a.append("799898989");
a.append("323232");
System.out.println(a);
//使用StringBuilder的capacity()方法可以查看其当前容量
System.out.println("a的容量为:"+a.capacity()+" a的长度为:"+a.length());
}
}
此时输出结果为
3、若一次追加的字符串长度超过了扩容一次之后的长度,其容量会直接扩容到与所添加的字符串长度相等的长度。
public class Test01 {
public static void main(String[] args) {
//无参构造初始容量为: 16
StringBuilder a = new StringBuilder();
a.append("2626ddfdvfgfgbgfgfdgdgdvffdgfgfdgfdgfdgfd");
System.out.println(a);
//使用StringBuilder的capacity()方法可以查看其当前容量
System.out.println("a的容量为:"+a.capacity()+" a的长度为:"+a.length());
}
}
此时的输出结果为