版权声明:本文为张仕宗原创文章,允许转载,转载时请务必标明文章原始出处 。 https://blog.csdn.net/zhang5476499/article/details/80603354
继上一篇自己动手写Java String类之后,今晚10点钟下班,感觉稍早,于是手痒痒就想自己动手来写StringBulder,毕竟程序员啥都讲究自己动手才能丰衣足食嘛!StringBuilder与String类的区别是String的变量内容是放在final char[]里面的,而StringBuilder是放在char[]里面的,听说String用到了常量池。以下为自己改版过后的StringBuilder,它实现了Serializable,CharSequence接口。JDK的StringBuilder除了实现这俩接口之外,还继承了AbstractStringBuilder抽象类,由于AbstractStringBuilder是在java.lang包里面,权限是default,学过Java的同学都知道默认的权限,其他包是无法继承的,所以MyStringBuilder就不继承AbstractStringBuilder了。以下为自己动手写MyStringBuilder。
import java.io.Serializable;
import java.util.Arrays;
public class MyStringBuilder implements Serializable, CharSequence{
private static final long serialVersionUID = 1L;
private char[] value;
private int count;
public MyStringBuilder() {
this(16);
}
public MyStringBuilder(CharSequence seq) {
}
public MyStringBuilder(int capacity) {
value = new char[capacity];
}
public MyStringBuilder(String str) {
value = new char[str.length()];
for(int i = 0; i < value.length; i++) {
value[i] = str.charAt(i);
}
count = str.length();
}
@Override
public int length() {
return count;
}
@Override
public char charAt(int index) {
//判断下标是否越界
if(index < 0 || index > count) {
throw new StringIndexOutOfBoundsException(index);
}
//返回数组中小标为index的元素
return value[index];
}
@Override
public CharSequence subSequence(int start, int end) {
// TODO Auto-generated method stub
return null;
}
public MyStringBuilder append(boolean b){
if(b) { //b为true
//1.为value数组扩容
value = Arrays.copyOf(value, count+4);
//.2给value赋值
value[count++] = 't';
value[count++] = 'r';
value[count++] = 'u';
value[count++] = 'e';
} else { //b为false
//1.为value数组扩容
value = Arrays.copyOf(value, count+5);
//.2给value赋值
value[count++] = 'f';
value[count++] = 'a';
value[count++] = 'l';
value[count++] = 's';
value[count++] = 'e';
}
return this;
}
@Override
public String toString() {
return new String(value);
}
public MyStringBuilder append(char c) {
//1.给value数组扩容
value = Arrays.copyOf(value, count+1);
//2.给value赋值
value[count++] = c;
//返回MyStringBuilder本身,供方法链调用
return this;
}
public MyStringBuilder append(char[] str) {
char[] newChar = new char[count+str.length]; //创建一个新数组,容纳新老字符
System.arraycopy(value, 0, newChar, 0, count); //将原数组的值塞进新数组的前半段
System.arraycopy(str, 0, newChar, count, str.length);//将要拼接的数组的值塞进新数组的后半段
value = Arrays.copyOf(newChar, newChar.length); //原来的value数组扩容
count = value.length;
return this;
}
public MyStringBuilder append(String string) {
if(string == null) { //如果对象为空,则返回"null"字符串
return appendNull();
}
//1.先对value扩容
value = Arrays.copyOf(value, count+string.length());
//2.调用String类的.getChars方法,将字符从此字符串复制到value字符数组。
string.getChars(0, string.length(), value, count);
//3.count长度增加
count += string.length();
return this;
}
private MyStringBuilder appendNull() {
value = Arrays.copyOf(value, count+4);
value[count++] = 'n';
value[count++] = 'u';
value[count++] = 'l';
value[count++] = 'l';
return this;
}
public MyStringBuilder append(float f) {
/**
* JDK是调用该类来完成转化的,FloatingDecimal.appendTo(f,this);
*/
String str = String.valueOf(f);
return this.append(str);
}
public MyStringBuilder append(double d) {
String str = String.valueOf(d);
return this.append(str);
}
public MyStringBuilder append(Object obj) {
if(obj == null) {
return appendNull();
}
return append(obj.toString());
}
public MyStringBuilder deleteCharAt(int index) {
if(index < 0 || index > count) {
throw new StringIndexOutOfBoundsException(index);
}
System.arraycopy(value, index+1, value, index, count-index-1);
count--;
return this;
}
/**
* 将字符数组倒置
* @return value 倒置后的字符数组
*/
public MyStringBuilder reverse() {
int n = count-1;
int i = 0;
//JDK使用的倒置算法比我的效率高,暂时读不懂它的代码
while(i < count/2) {
char cj = value[i]; //一边从头开始
char ck = value[n-i]; //一遍从尾开始
//两个位置的元素相互交换里面的内容
value[i] = ck;
value[n-i] = cj;
i++;
}
return this;
}
}
上诉只提供了StringBuilder常用的方法,并没用完全实现StringBuilder的全部功能,同时apend()的重载方法有很多,这里只给出了一些比较常见的参数,如:append(String str),append(char[] chars),append(boolean b),append(Object obj);等。当然了,我的字符串倒置reverse()估计效率也没用JDK提供的高,不过功能完成实现出来了就行了!
下面为测试StringBuilder和MyStringBuilder的代码:
public class TestMyStringBuilder {
public static void main(String[] args) {
char[] chars = new char[4];
chars[0] = 'J';
chars[1] = 'a';
chars[2] = 'v';
chars[3] = 'a';
String nullStr = null;
Student stu = new Student("1","22","男");
Student stuNull = null;
StringBuilder sb = new StringBuilder("");
System.out.println("JDK提供的StringBuilder:");
System.out.println(sb.append(true).append(' ')
.append(false).append(chars).append(nullStr).append("HelloJava")
.append(3.141592653f).append(10086.11).append(stu).append(stuNull)
.deleteCharAt(10).reverse());
System.out.println("长度:" + sb.length());
System.out.println("测试charAt:第10个字符" + sb.charAt(10)+",第20个字符:" + sb.charAt(20));
MyStringBuilder sb1 = new MyStringBuilder("");
System.out.println("自己实现的StringBuilder:");
System.out.println(sb1.append(true).append(' ')
.append(false).append(chars).append(nullStr).append("HelloJava")
.append(3.141592653f).append(10086.11).append(stu).append(stuNull)
.deleteCharAt(10).reverse());
System.out.println("长度:" + sb1.length());
System.out.println("测试charAt:第10个字符" + sb1.charAt(10)+",第20个字符:" + sb1.charAt(20));
}
}
以下为输出内容:
JDK提供的StringBuilder:
llun]男=xes ,22=ega ,1=di[ tnedutS11.680017295141.3avaJolleHllunavaeslaf eurt
长度:76
测试charAt:第10个字符 ,第20个字符:1
自己实现的StringBuilder:
llun]男=xes ,22=ega ,1=di[ tnedutS11.608017295141.3avaJolleHllunavaeslaf eurtl
长度:76
测试charAt:第10个字符 ,第20个字符:1