欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

自己动手写StringBulder

程序员文章站 2022-12-25 12:48:06
继上一篇自己动手写Java String类之后,今晚10点钟下班,感觉稍早,于是手痒痒就想自己动手来写StringBulder,毕竟程序员啥都讲究自己动手才能丰衣足食嘛!StringBuilder与String类的区别是String的变量内容是放在final char[]里面的,而StringBui... ......

继上一篇自己动手写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