自己動手寫StringBuilder類
阿新 • • 發佈:2018-11-08
繼上一篇自己動手寫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