1. 程式人生 > >自己動手寫StringBuilder類

自己動手寫StringBuilder類

繼上一篇自己動手寫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