为什么StringBuffer可以变长?
和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度
比如说new StringBuffer(“the”),其内部的字符数组的长度,是19,而不是3,这样调用插入和追加,在现成的数组的基础上就可以完成了。
如果追加的长度超过了19,就会分配一个新的数组,长度比原来多一些,把原来的数据复制到新的数组中,看上去 数组长度就变长了
length: “the”的长度 3
capacity: 分配的总空间 19
边界条件判断
插入之前,首先要判断的是一些边界条件。 比如插入位置是否合法,插入的字符串是否为空
扩容
插入字符串
修改length的值
最后修改length的值,是原来的值加上插入字符串的长度
insert(int, char)
参数是字符的insert方法,通过调用insert(int, String) 也就实现了。
append
追加,就是在最后位置插入。 所以不需要单独开发方法,直接调用insert方法,就能达到最后位置插入的效果
先写一个接口,需要实现以下的接口,功能有
package j2se;
public interface IStringBuffer {
public void append(String str);//追加字符串
public void append(char c);//追加字符
public void insert(int pos, char b);//指定位置插入字符
public void insert(int pos, String b);//指定位置插入字符串
public void delete(int start);//从开始位置删除剩下的
public void delete(int start, int end);//从开始位置删除结束位置-1
public void reverse();//反转
public int length();//返回长度
}
package j2se;
public class MyStringBuffer implements IStringBuffer{
//第一步:完后基础变量设置和构造函数的写入
int capacity = 16;//容量,一开始就有的长度
int length = 0;//数组本身长度
char[] value;//实际存放String数据的位置
//无参构造函数,根据容量初始化value
public MyStringBuffer() {
value = new char[capacity];
}
//有参构造方法,str是初始化的字符串
public MyStringBuffer(String str) {
this();//调用无参构造方法
if (null == str)
return;
if (capacity < str.length()) {
capacity = value.length * 2;
value = new char[capacity];
}
if (capacity >= str.length()) {
System.arraycopy(str.toCharArray(), 0, value, 0, str.length());
}
length = str.length();
}
//第二步:将简单方法写完,比如说完成返回字符串,长度和反转
//返回长度
public int length() {
return length;
}
//返回字符串
//将字符数组可以转化成字符串
public String toString() {
char[] realValue = new char[length];
System.arraycopy(value, 0 , realValue, 0, length);//将value的内容都复制到realValue
return new String (realValue);
}
//反转reverse
//方法:对半相互复制
//原理测试: 长度是6,双数,就是收尾互换,然后索引+1就行,交换次数/2,3次
//长度是5,单数,首尾互换就行了,然后中间不交换,交换次数/2,两次
//长度是3,012,0和2位置互换,1和互换
//长度是2,01,就是0和1交换
public void reverse() {
for (int i = 0; i < length / 2; i++) {
char temp = value[i];
value[i] = value[(length - 1) - i];//索引从0开始
value[(length - 1) - i] = temp;
}
}
//第三步:insert和append的方法
//考虑以下问题:
//边界条件和扩容
//先写insert字符串的方法
//insert字符和append的话直接调用insert字符串的方法
//o-pos-cs.length
//指定位置插入字符串
public void insert(int pos, String b) {
//判断边界条件
if (pos < 0) {
return;
}
if (pos > length) {
return;
}
if (null == b) {
return;
}
//扩容
while (length + b.length() > capacity) {
capacity = (int)((length + b.length()) * 1.5f);
char[] newValue = new char[capacity];
System.arraycopy(value, 0, newValue, 0, length);
value = newValue;//让value指向新的数组
}
char[] cs = b.toCharArray();//之后用数组的话,需要转换成数组
//先把已经存在的数据后移
System.arraycopy(value, pos, value, pos + cs.length, length - pos);
//把要插入的数据插入到指定位置
System.arraycopy(cs , 0, value, pos, cs.length);
length = length + cs.length;
}
//指定位置插入字符
public void insert(int pos, char b) {
insert(pos, String.valueOf(b));
}
//追加字符串
public void append(String str) {
insert(length, str);
}
//追加字符
public void append(char c) {
insert(length, String.valueOf(c));
}
//第四步:删除数组
//删除的数据假设在中间,将后面的数据移过来,再和前面的数据拼接在一起
//从开始位置删除结束位置-1
public void delete(int start, int end) {
//边界条件判断
if (start < 0) {
return;
}
if (start >= end) {
return;
}
if (end > length) {
return;
}
if (end < 0) {
return;
}
System.arraycopy(value, end, value, start, length - end);
length -= end - start;
}
//从开始位置删除剩下的
public void delete(int start) {
delete(start, length);
}
// public static void main(String[] args) {
// MyStringBuffer sb = new MyStringBuffer("there light");
//
//// sb.reverse();
// System.out.println(sb);
//
// sb.insert(0, "let ");
// System.out.println(sb);
// sb.insert(0, "be ");
// System.out.println(sb);
// sb.append("!");
// System.out.println(sb);
// sb.append("?");
// System.out.println(sb);
// //sb.reverse();
// //System.out.println(sb);
//
// sb.delete(0,7);//0-6
// System.out.println(sb);
// sb.delete(6);//删除从6后的
// System.out.println(sb);
// }
//MyStringBuffer和StringBuffer的性能
//发现实际效果并不明显
public static void main(String[] args) {
String ss = random();
stringBuffer(ss);
MyStringBuffer(ss);
}
//随机字符串
public static String random() {
char[] cs = new char[10];
for (int i = 0; i < cs.length; i++) {
cs[i] = (char)(Math.random() * 127);
}
return new String(cs);
}
//stringBuffer
public static void stringBuffer(String str) {
StringBuffer sb = new StringBuffer();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
sb.append(str);
}
long endTime = System.currentTimeMillis();
System.out.println("StringBuffer耗时" + (endTime - startTime) + "毫秒");
}
//MyStringBuffer
public static void MyStringBuffer(String str) {
MyStringBuffer msb = new MyStringBuffer();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
msb.append(str);
}
long endTime = System.currentTimeMillis();
System.out.println("MyStringBuffer耗时" + (endTime - startTime) + "毫秒");
}
}