您所在的位置:主页 > JAVA技术 >

自己动手写StringBulder

时间:2018-06-13 10:52来源:未知 作者:os 点击:

自己动手写Java String类之后,就想自己动手来写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