封装一个类似的StringBuilder类

本文介绍如何封装一个类似于Java的StringBuilder类,包括append、length、charAt、indexOf和insert等方法。讲解了StringBuilder内部使用char数组存储数据,通过count变量跟踪实际长度,并讨论了各方法的实现细节。虽然insert方法使用了多个for循环,但作者承认存在优化空间,欢迎大家提供改进意见。

主要封装的几个常用的方法:

  • append:追加
  • length:获取长度
  • charAt:获取字符
  • indexOf:获取指定字符串第一个出现的索引位置
  • insert:插入

 StringBuilder底层是以char类型数组来实现的,所有要有一个char类型的数组来进行存储数据

用count这个变量来记录实际的长度。

默认的初始容量为16字符,也可以指定初始容量

    private char[] value; // 存储数据
    private final int CAPACITY = 16; // 默认的初始化的容量长度
    private int count; // 记录实际容量长度
    // 构造方法
    // 初始化容量为16
    public MyStringBuilder() {
        value = new char[CAPACITY];
    }

    // 指定初始化容量
    public MyStringBuilder(int newCapacity) {
        value = new char[newCapacity];
    }
    // 初始化指定的字符串
    public MyStringBuilder(String str){
        value = new char[str.length() + CAPACITY];
        copyArray(str, 0);
        count = str.length();
    }
    // 把字符串添加到数组里
    private void copyArray(String str, int dstBegin) {
        str.getChars(0, str.length(), value, dstBegin);
    }

第一个方法:append

     /**
     * 把指定的字符串追加到结尾
     * @param str 追加字符串
     * @return this
     */
    public MyStringBuilder append(String str) {
        /*
            首先要先确定数组的容量是否够实际所要存储的最小容量
            所以要进行判断:value.length 是否大于 实际要求最小的容量 count + str.length
         */
        minCapacity(str);
        copyArray(str, count);
        count += str.length();
        return this;
    }

    /**
     * 判断是否符合所要求的最小容量
     * @param str 追加的字符串
     */
    private void minCapacity(String str) {
        // 得到最小的容量
        int minLen = count + str.length();
        // 进行判断,当小于0时,说明当前的真实容量vlaue.length是不符合最小的容量
        // 要进行扩容
        if(value.length - minLen < 0) {
            // 扩容
            enlargeArrayLength(minLen);
        }
    }

    /**
     * 计算一个合理的容量长度
     * @param minCapacity
     */
    private void enlargeArrayLength(int minCapacity) {
        // 给出一个合理的容量长度,当前容量的1.5倍
        int newCapacity = (value.length >> 1) + value.length;
        // 判断合理的容量长度是否大小要求最小的容量长度
        if(newCapacity - minCapacity < 0) {
            // 说明计算出的合理的容量长度不符合最小的容量长度
            // 直接用最小的容量长度
            newCapacity = minCapacity;
        }
        // 进行扩容
        arrayCopyOf(newCapacity);
    }

    /**
     * 对数组进行扩容
     * @param newCapacity 扩容长度
     */
    private void arrayCopyOf(int newCapacity) {
        this.value = Arrays.copyOf(value, newCapacity);
    }

第二个方法:length 

    /**
     * 返回实际容量长度
     * @return count 长度
     */
    // length也是最简单的方法直接把count返回就行了
    public int length() {
        return count;
    }

第三个方法:charAt

     /**
     * 返回指定索引的char类型元素
     * @param index 索引
     * @return char类型元素
     */
    public char charAt(int index) {
        // 要先判断index是否在合理的范围之内
        chargeIndex(index);
        return value[index];
    }

    /**
     * 判断index是否在合理的范围内
     * @param index 索引
     */
    private void chargeIndex(int index) {
        if(index < 0 || index >= count) {
            // 说明不是在范围内
            // 抛出异常
            throw new StringIndexOutOfBoundsException(index);
        }
    }

第四个方法:indexOf

    /**
     * 返回指定字符串第一次出现的索引
     * @param str 字符串
     * @return  索引
     */
    public int indexOf(String str) {
        return firstString(str);
    }

    /**
     * 返回对应的索引
     * @param str 字符串
     * @return 字符串第一次出现的索引
     */
    private int firstString(String str) {
        // 第一种写法
        // String stringValue = String.copyValueOf(value);
        // return stringValue.indexOf(str);
        // 第二种写法
        int index = -1;
        int strLen = str.length();
        for(int i = 0; i < count; i++) {
            if(value[i] == str.charAt(0)) {
                int count = i +1;
                for(int j = 1; j < strLen; j++) {
                    if(value[count] != str.charAt(j)) {
                        break;
                    }
                    if(j == strLen - 1) {
                        index = i;
                    }
                    count++;
                }
            }
        }
        return index;
    }

第五种方法:insert

        实现这个方法的功能,我写的不好。一个方法里用了三个for循环,但是我想不出用别的方法来更好的实现这个功能,所以只能暂时这样了,大家看看就好。

     /**
     * 将指定的字符串插入到指定位置
     * @param offset 索引
     * @param str 插入字符串
     * @return this
     */
    public MyStringBuilder insert(int offset, String str) {
        // 判断插入的索引是否在范围内
        chargeIndex(offset);
        // 插入
        arraycopy(offset, str);
        return this;
    }

    /**
     *  把指定的字符串插入到指定的索引
     * @param offset 插入位置
     * @param str   字符串
     */
    private void arraycopy(int offset, String str) {
        // 把字符串转换为char类型的数组
        char[] strChar = str.toCharArray();
        int num = offset + strChar.length;
        char[] newValue = new char[value.length + strChar.length];
        int n = offset;
        // 把指定索引前面的元素先装到newValue数组内
        for(int i = 0; i < offset; i++) {
            newValue[i] = value[i];
        }
        // 索引之后要插入的字符串装到newValue数组中
        for(int i = 0; i < strChar.length; i++) {
            newValue[n++] = strChar[i];
        }
        // 再把剩余的value元素放到newValue数组中
        for(int i = offset; i < count; i++) {
            newValue[num++] = value[i];
        }
        // 更新count
        count += strChar.length;
        value = newValue;
    }

 本人水平有限,方法写的指定不是很好,供大家参考参考。

表喷我,好怕怕!!!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值