JDK1.8.0_161_64源码解析系列之java.lang.AbstractStringBuilder
1、类的声明
abstract class AbstractStringBuilder implements Appendable, CharSequence
1.1、CharSequence
用来获取一些基本信息的接口?
1、int length();
获取长度 原文:(Returns the length of this character sequence)
2、charAt(int index)
返回指定位置的字符
3、subSequence(int start, int end);
返回一个序列的子序列,例如,返回字符串的子串
4、toString()
返回string
1.2、Appendable
定义添加规则,也就是怎么往里面添加
2、类的变量
2.1 char[] value;
用来存储的地方
2.2 int count
实际用到的数量
- 是可变的
- 可直接对value和count进行操作
- value 是动态数组
- value.length!=count;
3、构造函数
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
第一个构造函数是序列化不可缺少的,第二个是用创建一个指定容量的AbstractStringBuilder
4、基本方法
public int length() {
return count;
}
public int capacity() {
return value.length;
}
第一个返回当前实际用量,第二个是返回的是容量,也就是说,第一个返回的是桶里水的多少,第二个返回的是桶的大小
5、空间处理
public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0)//如果>0往下走
ensureCapacityInternal(minimumCapacity);
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0) {
/*如果需要的比现有的最大容量还要大,则进行重新分配value*/
value = Arrays.copyOf(value,
newCapacity(minimumCapacity));
}
}
/*定义可分配的最大值*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
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;
}
- 分配空间的时候,先判断所需要的空间数是否大于0
- 若大于0 ,则判断是否大于现有的容量
- 若大于现有的容量,则对现有的容量扩大2倍
- 若扩大2倍以后的容量还打不到所需的容量,则直接扩大到所需的容量
public void trimToSize() {
if (count < value.length) {
value = Arrays.copyOf(value, count);
}
}
- 用于去除没用的空间
- 费时间
- 如果桶里的水比桶的容量小,那么换一个和水容量一样的桶
6、append
append(Object obj)
public AbstractStringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
调用 append(String str) 接口
append(String str)
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
null也会在后面添加
如果为空添加
1处的意思是 获取字符串长度
2处的意思是 开辟空间,开辟大小为原容量的2倍或者count+len的大小
3处的意思是 将str中的数据从 0 开始,到 len 结束 复制到value中 从 count开始的位置,通俗的说,就是把str中的数据加载到value的后面
append(StringBuffer sb)
public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null)
return appendNull();
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
count += len;
return this;
}
与 上一个 append(String str)类似,只是重写了复制方法,复制参数还是一样的
append(AbstractStringBuilder asb)
AbstractStringBuilder append(AbstractStringBuilder asb) {
if (asb == null)
return appendNull();
int len = asb.length();
ensureCapacityInternal(count + len);
asb.getChars(0, len, value, count);
count += len;
return this;
}
相似的方法
append(CharSequence s)
@Override
public AbstractStringBuilder append(CharSequence s) {
if (s == null)
return appendNull();
if (s instanceof String)
return this.append((String)s);
if (s instanceof AbstractStringBuilder)
return this.append((AbstractStringBuilder)s);
return this.append(s, 0, s.length());
}
对s进行分类处理,若不属于上面的类,则调用本地方法this.append(s, 0, s.length());
appendNull()
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
看源码的样子是把 "null" 放进去了。。。。晕 !
append(CharSequence s, int start, int end)
public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null)
s = "null";
if ((start < 0) || (start > end) || (end > s.length()))
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() "
+ s.length());
int len = end - start;
ensureCapacityInternal(count + len);
for (int i = start, j = count; i < end; i++, j++)//1
value[j] = s.charAt(i);
count += len;
return this;
}
其实就是通过charAt 方法获取每个字符,然后把这些字符一个个加到value后面
- 1 处的意思是遍历下s,然后把s中的一个个都加到value后(value就是存储数据的地方)
append(char[] str)
public AbstractStringBuilder append(char[] str) {
int len = str.length;
ensureCapacityInternal(count + len);
System.arraycopy(str, 0, value, count, len);//1
count += len;
return this;
}
直接调用的系统的复制方法,将str复制到value之后
- 1处的意思是 str字符串, 0 要复制的起始位置,value 目标字符串,count 目标字符串起始位置,len 要复制的长度
append(char str[], int offset, int len)
public AbstractStringBuilder append(char str[], int offset, int len) {
if (len > 0) // let arraycopy report AIOOBE for len < 0
ensureCapacityInternal(count + len);
System.arraycopy(str, offset, value, count, len);
count += len;
return this;
}
相似处理方法
append(boolean b)
public AbstractStringBuilder append(boolean b) {
if (b) {
ensureCapacityInternal(count + 4);
value[count++] = 't';
value[count++] = 'r';
value[count++] = 'u';
value[count++] = 'e';
} else {
ensureCapacityInternal(count + 5);
value[count++] = 'f';
value[count++] = 'a';
value[count++] = 'l';
value[count++] = 's';
value[count++] = 'e';
}
return this;
}
其实就是把 true和false存到 数组里面
append(int i)
public AbstractStringBuilder append(int i) {
if (i == Integer.MIN_VALUE) {
append("-2147483648");
return this;
}
int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
: Integer.stringSize(i);
int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded);
Integer.getChars(i, spaceNeeded, value);
count = spaceNeeded;
return this;
}
处理方法相似,只不过复制方法不一样
7、delete
public AbstractStringBuilder delete(int start, int end) {
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
end = count;
if (start > end)
throw new StringIndexOutOfBoundsException();
int len = end - start;
if (len > 0) {
System.arraycopy(value, start+len, value, start, count-end);
count -= len;
}
return this;
}
其实就是把大容量数据复制到小容量容器中,多于的部分就被删除了
8、replace
replace(int start, int end, String str)
public AbstractStringBuilder replace(int start, int end, String str) {
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (start > count)
throw new StringIndexOutOfBoundsException("start > length()");
if (start > end)
throw new StringIndexOutOfBoundsException("start > end");
if (end > count)
end = count;
int len = str.length();
int newCount = count + len - (end - start);//1
ensureCapacityInternal(newCount);
System.arraycopy(value, end, value, start + len, count - end);//2
str.getChars(value, start);//3
count = newCount;
return this;
}
1处的意思是 将现有数据比元数据多的资源加上
通俗理解就是 有一个装满土的口袋,心在想把里面的一部分土换成更大的石头,但是换的话,空间就不够了,这时候就需要把布袋加大,这个大的体积就是 石头的体积减去换去的杀的体积
2处的意思是 ,将从end以后的数据整个挪到start这个节点后
3处的意思是将数据复制到start开始位置
整个过程的通俗解释
1 增加空间
先把源字符串比目标多的空间申请上
2 腾位置
把需要插入的数据位置腾出来
3 写数据
其实 ,自己根据源码画个图就出来了
9、 substring
substring(int start, int end)
public String substring(int start, int end) {
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
throw new StringIndexOutOfBoundsException(end);
if (start > end)
throw new StringIndexOutOfBoundsException(end - start);
return new String(value, start, end - start);
}
就是新建字符串的过程
10、insert
insert(int index, char[] str, int offset,int len)
- index 插入的位置
- str 插入的内容
- offset 插入数据的起始位置
- len 插入数据的长度
public AbstractStringBuilder insert(int index, char[] str, int offset, int len)
{
if ((index < 0) || (index > length()))
throw new StringIndexOutOfBoundsException(index);
if ((offset < 0) || (len < 0) || (offset > str.length - len))
throw new StringIndexOutOfBoundsException(
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
ensureCapacityInternal(count + len);//1
System.arraycopy(value, index, value, index + len, count - index);//2
System.arraycopy(str, offset, value, index, len);//3
count += len;
return this;
}
- 1处的意思是开辟空间
- 2处的意思是挪位置
- 3处的意思是插入数据
insert(int offset, String str)
- offset 要出入的位置
- str 要插入的字符串
public AbstractStringBuilder insert(int offset, String str) {
if ((offset < 0) || (offset > length()))
throw new StringIndexOutOfBoundsException(offset);
if (str == null)
str = "null";
int len = str.length();
ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);//1
str.getChars(value, offset);//2
count += len;
return this;
}
- 1处意思是腾位置
- 2处时插入数据
insert(int offset, char[] str)
public AbstractStringBuilder insert(int offset, char[] str) {
if ((offset < 0) || (offset > length()))
throw new StringIndexOutOfBoundsException(offset);
int len = str.length;
ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);
System.arraycopy(str, 0, value, offset, len);
count += len;
return this;
}
跟上面的方法差不多不做详解
11、reverse
倒装
public AbstractStringBuilder reverse() {
boolean hasSurrogates = false;
int n = count - 1;
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = value[j];
char ck = value[k];
value[j] = ck;
value[k] = cj;
if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) {
hasSurrogates = true;
}
}
if (hasSurrogates) {
reverseAllValidSurrogatePairs();
}
return this;
}
/** Outlined helper method for reverse() */
private void reverseAllValidSurrogatePairs() {
for (int i = 0; i < count - 1; i++) {
char c2 = value[i];
if (Character.isLowSurrogate(c2)) {
char c1 = value[i + 1];
if (Character.isHighSurrogate(c1)) {
value[i++] = c1;
value[i] = c2;
}
}
}
}