StringBuild及StringBuffer

1.介绍

   1.1 String是一个固定的字符对象一旦初始化完就不可改变。而StringBuild和StringBuffer是java里处理可变的字符串。StringBuild不是现场安全的,StringBuffer是现场安全的。

  1.2 主要方法,主要有四类,尾部追加append(),插入insert(),删除delete0及分割字串substring()等、

1.3实现原理

StringBuild继承与抽象类AbstractStringBuilder。大部分暴露的方法的实现都是调用AbstractStringBuilder对象的里方法。

StringBuffer继承与抽象类AbstractStringBuilder。大部分暴露的方法的实现都是调用AbstractStringBuilder对象里类方法。由于StringBuffer是现场安全的,所以它的大部分方法都使用了synchronized保证同步。

 例如如下分别是StringBuild类和StringBuffer类里的的append方法。

//StringBuilder类里的append方法

 public StringBuilder append(String str) {

        append0(str);

        return this;

 }

 

 //StringBuffer类里的append方法

 public synchronized StringBuffer append(Stringstring) {

        append0(string);

        return this;

 }

         通过源码我们很清楚的看到,StringBuild和StringBuffer实现基本都是使用的AbstractStringBuilder,区别就是有没有使用synchronized区别。我们只要研究AbstractStringBuilder类里实现,就可以学习到可变字符串的实现原理了

2.AbstractStringBuilder主要方法介绍

     2.1)AbstractStringBuilder类思想

    其实就是有字符数组的成员变量[char[]value],一个记录长度的成员变量[intcount],默认容量就是16。实现原理就是插入新东西的时候,判断剩余容量是否装载的下插入的字符类型,不够的话扩容量,把当前字符数组容量扩大1.5倍,把旧的字符串复制进来,再把新的字符串复制进去;够的话直接插入就行。

  下面就分别通过源码解读几个不同类型的几个经典方法,分析具体的实现思想、

 

2.2)三个构造函数

AbstractStringBuilder()

//构造容量默认是16的AbstractStringBuilder对象

AbstractStringBuilder(int capacity)

//构造容量是capacity的AbstractStringBuilder对象

    AbstractStringBuilder(String string)

//构造内容是string的AbstractStringBuilder对象

2.3)尾部追加的方法:append0(char[] chars)

   原理:追加字符数组的时候,判断剩余容量是否够装载追加的串,够的话直接插入,不够的话,扩容1.5倍,在把旧串复制进来,把新串追加到尾部。

final void append0(char[] chars) {

       //获取到需要的总长度

       int newCount = count + chars.length;

           //总长度超过字符数组的长度,扩容量

       if (newCount > value.length) {

           //扩容方法下面有介绍

           enlargeBuffer(newCount);

       }

           //插入新的字符数组到原始的value字符数组里

       System.arraycopy(chars, 0, value, count, chars.length);

       count = newCount;

}

 

 

private void enlargeBuffer(int min) {

      //当前数组扩容1.5倍

int newCount = ((value.length >> 1) + value.length) + 2;

//如果扩容后的newCount还是小于min。使用min大小,否则使用newCount大小

       char[] newData = new char[min > newCount ? min : newCount];

          //把旧的字符数字复制进来

       System.arraycopy(value, 0, newData, 0, count);

         //重写对成员变量赋值

       value = newData;

       shared = false;

}

举例:给字符数组长度是5,内容是stri里插入字符串ab,判断剩余容量是1,装不下ab,直接容量扩大1.5倍,变成7,把旧的串复制进来,同时在把ab复制进来。

 

2.4)合适位置插入新串的方法:insert0(int index, char[] chars)

 

原理: 首先判断容量够不,够的话,调用move方法,移动字符数据的内容。

其实就是把index到lenght的位置字符移动到index+size[新插入字符的长度]位置以后,预留出来index到index+size的位置插入新串即可;如果容量不够,扩容1.5倍,先把0-index位置的字符串复制进来,再把index到length位置的字符串复制到

index+size以后,最后再把新的串插入到index到index+size的位置。

 

final void insert0(int index, char[]chars) {

       //异常下标处理

       if (0 > index || index > count) {

           throw new StringIndexOutOfBoundsException(index);

       }

      //字符数组有内容,执行插入

       if (chars.length != 0) {

          //合理扩容及移动字符串,留出来合适位置插入新串

           move(chars.length, index);

            //把新的串插入到index位置即可

           System.arraycopy(chars, 0, value, index, chars.length);

           count += chars.length;

       }

   }

 private void move(int size, int index) {

       int newCount;

       if (value.length - count >= size) {

          //数组容量够转下新的串,把旧的串从index到count位置的字串复制到value里的 index + size位置以后,留出来的index到index + size位置刚好复制新插入的串

           if (!shared) {

                System.arraycopy(value, index,value, index + size, count

                        - index); // index ==count case is no-op

                return;

           }

           newCount = value.length;

       } else {

          //扩容量

           int a = count + size, b = (value.length << 1) + 2;

           newCount = a > b ? a : b;

       }

 

       char[] newData = new char[newCount];

      //把旧串0到index位置的串复制到新的数组value里

       System.arraycopy(value, 0, newData, 0, index);

       // 复制旧串index到count位置到新串index + size位置以后,留出来的index到index + size位置刚好复制新插入的串

       System.arraycopy(value, index, newData, index + size, count - index);

       value = newData;

       shared = false;

}

举例:给一个字符串长度是5,内容是abcde,容量是9的字符数组里,在2的位置插入gh。

1)     判断容量够,不用扩容,直接把2[想插入的起始位置]-4[旧字符串的长度]。的字符串整齐向后两个位置复制。变成abcdcde,中间留了两个位置2[想插入的起始位置]-4[插入起始位置加上插入的串长度]。

2)     直接在2-4的位置覆盖插入gh即可。


  2.5:总结

   其它类似于字符串的分割方法substring()、替换方法 replace0()、删除方法delete0(),要不较为简单,要不实现类似,就不在介绍。学习和了解源码的实现思路,学习到核心思想和编程要点就最重要的。




  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值