主要封装的几个常用的方法:
- append:追加
- length:获取长度
- charAt:获取字符
- indexOf:获取指定字符串第一个出现的索引位置
- insert:插入
StringBuilder底层是以char类型数组来实现的,所有要有一个char类型的数组来进行存储数据
用count这个变量来记录实际的长度。
默认的初始容量为16字符,也可以指定初始容量
private char[] value; // 存储数据
private final int CAPACITY = 16; // 默认的初始化的容量长度
private int count; // 记录实际容量长度
// 构造方法
// 初始化容量为16
public MyStringBuilder() {
value = new char[CAPACITY];
}
// 指定初始化容量
public MyStringBuilder(int newCapacity) {
value = new char[newCapacity];
}
// 初始化指定的字符串
public MyStringBuilder(String str){
value = new char[str.length() + CAPACITY];
copyArray(str, 0);
count = str.length();
}
// 把字符串添加到数组里
private void copyArray(String str, int dstBegin) {
str.getChars(0, str.length(), value, dstBegin);
}
第一个方法:append
/**
* 把指定的字符串追加到结尾
* @param str 追加字符串
* @return this
*/
public MyStringBuilder append(String str) {
/*
首先要先确定数组的容量是否够实际所要存储的最小容量
所以要进行判断:value.length 是否大于 实际要求最小的容量 count + str.length
*/
minCapacity(str);
copyArray(str, count);
count += str.length();
return this;
}
/**
* 判断是否符合所要求的最小容量
* @param str 追加的字符串
*/
private void minCapacity(String str) {
// 得到最小的容量
int minLen = count + str.length();
// 进行判断,当小于0时,说明当前的真实容量vlaue.length是不符合最小的容量
// 要进行扩容
if(value.length - minLen < 0) {
// 扩容
enlargeArrayLength(minLen);
}
}
/**
* 计算一个合理的容量长度
* @param minCapacity
*/
private void enlargeArrayLength(int minCapacity) {
// 给出一个合理的容量长度,当前容量的1.5倍
int newCapacity = (value.length >> 1) + value.length;
// 判断合理的容量长度是否大小要求最小的容量长度
if(newCapacity - minCapacity < 0) {
// 说明计算出的合理的容量长度不符合最小的容量长度
// 直接用最小的容量长度
newCapacity = minCapacity;
}
// 进行扩容
arrayCopyOf(newCapacity);
}
/**
* 对数组进行扩容
* @param newCapacity 扩容长度
*/
private void arrayCopyOf(int newCapacity) {
this.value = Arrays.copyOf(value, newCapacity);
}
第二个方法:length
/**
* 返回实际容量长度
* @return count 长度
*/
// length也是最简单的方法直接把count返回就行了
public int length() {
return count;
}
第三个方法:charAt
/**
* 返回指定索引的char类型元素
* @param index 索引
* @return char类型元素
*/
public char charAt(int index) {
// 要先判断index是否在合理的范围之内
chargeIndex(index);
return value[index];
}
/**
* 判断index是否在合理的范围内
* @param index 索引
*/
private void chargeIndex(int index) {
if(index < 0 || index >= count) {
// 说明不是在范围内
// 抛出异常
throw new StringIndexOutOfBoundsException(index);
}
}
第四个方法:indexOf
/**
* 返回指定字符串第一次出现的索引
* @param str 字符串
* @return 索引
*/
public int indexOf(String str) {
return firstString(str);
}
/**
* 返回对应的索引
* @param str 字符串
* @return 字符串第一次出现的索引
*/
private int firstString(String str) {
// 第一种写法
// String stringValue = String.copyValueOf(value);
// return stringValue.indexOf(str);
// 第二种写法
int index = -1;
int strLen = str.length();
for(int i = 0; i < count; i++) {
if(value[i] == str.charAt(0)) {
int count = i +1;
for(int j = 1; j < strLen; j++) {
if(value[count] != str.charAt(j)) {
break;
}
if(j == strLen - 1) {
index = i;
}
count++;
}
}
}
return index;
}
第五种方法:insert
实现这个方法的功能,我写的不好。一个方法里用了三个for循环,但是我想不出用别的方法来更好的实现这个功能,所以只能暂时这样了,大家看看就好。
/**
* 将指定的字符串插入到指定位置
* @param offset 索引
* @param str 插入字符串
* @return this
*/
public MyStringBuilder insert(int offset, String str) {
// 判断插入的索引是否在范围内
chargeIndex(offset);
// 插入
arraycopy(offset, str);
return this;
}
/**
* 把指定的字符串插入到指定的索引
* @param offset 插入位置
* @param str 字符串
*/
private void arraycopy(int offset, String str) {
// 把字符串转换为char类型的数组
char[] strChar = str.toCharArray();
int num = offset + strChar.length;
char[] newValue = new char[value.length + strChar.length];
int n = offset;
// 把指定索引前面的元素先装到newValue数组内
for(int i = 0; i < offset; i++) {
newValue[i] = value[i];
}
// 索引之后要插入的字符串装到newValue数组中
for(int i = 0; i < strChar.length; i++) {
newValue[n++] = strChar[i];
}
// 再把剩余的value元素放到newValue数组中
for(int i = offset; i < count; i++) {
newValue[num++] = value[i];
}
// 更新count
count += strChar.length;
value = newValue;
}
本人水平有限,方法写的指定不是很好,供大家参考参考。
表喷我,好怕怕!!!