基本知识点
源码解析
StringBuilder继承了父类AbstractStringBuilder,实现了接口:Appendable:可添加的;Comparable:可比较的字符串;CharSequence:可排序的字符穿;public final class StringBuilder extends AbstractStringBuilder implements Appendable, java.io.Serializable, Comparable<StringBuilder>, CharSequence
构造方法:默认容量为16;通过StringBuilder的构造方法传给父类的构造方法
public StringBuilder(int capacity) { super(capacity); }
AbstractStringBuilder(int capacity) { if (COMPACT_STRINGS) { value = new byte[capacity]; coder = LATIN1; } else { value = StringUTF16.newBytesFor(capacity); coder = UTF16; } }
- 构造函数定义: -
AbstractStringBuilder(int capacity)
是构造函数,接受一个整数参数capacity
,表示初始容量。- 条件判断
if (COMPACT_STRINGS)
: -COMPACT_STRINGS
是一个静态常量,通常用来指示是否使用紧凑字符串表示。在 Java 9 及以后的版本中,引入了紧凑字符串(Compact Strings)特性,目的是为了节省内存。当COMPACT_STRINGS
为true
时,表示使用紧凑字符串表示。- 紧凑字符串的处理: -
value = new byte[capacity];
:如果使用紧凑字符串,value
数组被初始化为一个字节数组,大小为capacity
。这意味着每个字符将使用一个字节来表示,适用于拉丁字符(如英文字母和数字)。 -coder = LATIN1;
:coder
变量被设置为LATIN1
,表示当前使用的编码方式是 Latin-1 编码。- 非紧凑字符串的处理: -
value = StringUTF16.newBytesFor(capacity);
:如果不使用紧凑字符串,value
将被初始化为 UTF-16 编码的字节数组。StringUTF16.newBytesFor(capacity)
是一个方法,用于根据给定的容量返回适合 UTF-16 的字节数组。 -coder = UTF16;
:coder
变量被设置为UTF16
,表示当前使用的编码方式是 UTF-16 编码。
append()方法源码解析
测试代码:判断是否扩容
public class Tesr2 { public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("hello"); System.out.println(stringBuilder); } }
第一步:进入StringBuilder的append方法:将hello传递给这个方法
public StringBuilder append(String str) { super.append(str); return this;
第二步:进入父类的这个方法:
获取hello的长度,count是指目前数组中存储的数量。
minimumCapacity:目前真实存储的+刚传进来的
public AbstractStringBuilder append(String str) { if (str == null) { return appendNull(); } int len = str.length(); ensureCapacityInternal(count + len); putStringAt(count, str); count += len; return this; }
第三步:进入ensureCapacticyInteral()方法。
判断是否扩容
coder讲解:
1. LATIN1:这种编码方式使用一个字节表示一个字符,适用于 ASCII 字符和一些西欧字符。其值通常为
0
。2. UTF16:这种编码方式使用两个字节表示一个字符(大部分常用字符),其值通常为
1
。
coder
的作用 :内存优化:通过使用coder
,AbstractStringBuilder
可以根据实际的字符编码方式来优化内存使用。例如,对于只包含 Latin-1 字符的字符串,可以使用更少的内存(一个字节)来存储字符,而对于包含更复杂字符的字符串,则使用 UTF-16 编码(两个字节)。容量计算:在代码中,
coder
被用来计算当前字符数组的实际容量。例如,oldCapacity
的计算是通过右移操作来实现的:
int oldCapacity = value.length >> coder;
如果
coder
是0
(即LATIN1
),oldCapacity
等于value.length
。如果
coder
是1
(即UTF16
),oldCapacity
等于value.length / 2
。原理:二进制右移运算符。
private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code int oldCapacity = value.length >> coder; //计算旧数组的容量 if (minimumCapacity - oldCapacity > 0) { //如果九数组容量小于最小数组存储量,则扩容 value = Arrays.copyOf(value, newCapacity(minimumCapacity) << coder); } }
字符串扩容为:原来的容量*2+2; (没超16按这个算法,超过了按传的字符串扩容,比如:43就扩容到43)
mincapacity为现存储容量;
oldLength = 16;
newLength = 现存储容量;
growth 为增加容量;
length为新的数组容量;
private int newCapacity(int minCapacity) { int oldLength = value.length; int newLength = minCapacity << coder; int growth = newLength - oldLength; int length = ArraysSupport.newLength(oldLength, growth, oldLength + (2 << coder)); if (length == Integer.MAX_VALUE) { throw new OutOfMemoryError("Required length exceeds implementation limit"); } return length >> coder; }
进入newLength方法:传入参数举例:16,(27,18)最大值。 = 16+27 = 43
int prefLength = oldLength + Math.max(minGrowth, prefGrowth);
构造方法
常用方法:增删改,可查看帮助文档。