MyStringBuffer对字符串的一些操作,比如插入和删除

MyStringBuffer对字符串的一些操作,比如插入和删除

    • 1.写代码前需要考虑的问题
    • 2. 写一个接口
    • 3.实现这个接口

以how2j上部分代码作为参考


1.写代码前需要考虑的问题

为什么StringBuffer可以变长?

和String内部是一个字符数组一样,StringBuffer也维护了一个字符数组。 但是,这个字符数组,留有冗余长度
比如说new StringBuffer(“the”),其内部的字符数组的长度,是19,而不是3,这样调用插入和追加,在现成的数组的基础上就可以完成了。
如果追加的长度超过了19,就会分配一个新的数组,长度比原来多一些,把原来的数据复制到新的数组中,看上去 数组长度就变长了
length: “the”的长度 3
capacity: 分配的总空间 19

边界条件判断

插入之前,首先要判断的是一些边界条件。 比如插入位置是否合法,插入的字符串是否为空

扩容

  1. 要判断是否需要扩容。 如果插入的字符串加上已经存在的内容的总长度超过了容量,那么就需要扩容。
  2. 数组的长度是固定的,不能改变的,数组本身不支持扩容。 我们使用变通的方式来解决这个问题。
  3. 根据需要插入的字符串的长度和已经存在的内容的长度,计算出一个新的容量。 然后根据这个容量,创建一个新的数组,接着把原来的数组的内容,复制到这个新的数组中来。并且让value这个引用,指向新的数组,从而达到扩容的效果。

插入字符串

  1. 找到要插入字符串的位置,从这个位置开始,把原数据看成两段,把后半段向后挪动一个距离,这个距离刚好是插入字符串的长度
  2. 然后把要插入的数据,插入这个挪出来的,刚刚好的位置里。

修改length的值
最后修改length的值,是原来的值加上插入字符串的长度

insert(int, char)

参数是字符的insert方法,通过调用insert(int, String) 也就实现了。

append

追加,就是在最后位置插入。 所以不需要单独开发方法,直接调用insert方法,就能达到最后位置插入的效果


2. 写一个接口

先写一个接口,需要实现以下的接口,功能有

  1. 反转
  2. 插入
  3. 删除
  4. 长度
  5. 返回本身字符串
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();//返回长度

}

3.实现这个接口

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) + "毫秒"); 
	}
}

你可能感兴趣的:(Java基础)