美文网首页Java8_131 rt包源码阅读记录
java.lang.StringBuilder、StringBu

java.lang.StringBuilder、StringBu

作者: Oliver_Li | 来源:发表于2019-12-08 17:49 被阅读0次

    1. 描述:

    • StringBuilderStringBuffer都是AbstractStringBuilder的子类,String的可变方式,String不可变操作只能new一个新对象,效率不高。
    • 字符串类都使用字符数组保存,String数组的长度是固定的,这两个类可变,所以会有数组长度变化的问题。
    • StringBuilder线程不安全,StringBuffer线程安全但速度相比较慢,但拼接肯定都比String快。
    • StringBuilder、StringBuffer,主要就是append()insert()的各种重载方法对value[]进行操作。
    • 核心字段(字段在父类AbstractStringBuilder中):
      • char[] value:和String一样,StringBuilder、StringBuffer也是字符数组,但可变。
      • int count:存储value[]已有元素个数。数组总长直接调用value.length
      • private transient char[] toStringCache;:StringBuilder独有的value[]缓存,后面会具体说。

    2. 构造函数(StringBuilder)

    //以入参”AAAA“为例
    public StringBuilder(String str) {
        //初始数组长度就是4 + 16
        super(str.length() + 16);
        //调用AbstractStringBuilder的append(str),StringBuilder和StringBuffer的父类
        append(str);
    }
    
    public AbstractStringBuilder append(String str) {
        if (str == null)
            //数组当前后添加{'n','u','l','l'}
            return appendNull();
        int len = str.length();
        //扩容
        ensureCapacityInternal(count + len);
        //利用System.arraycopy()把str补到后面
        str.getChars(0, len, value, count);
        //记录已有元素个数
        count += len;
        return this;
    }
    
    //计算扩容长度,用Arrays.copyOf()设置value[]
    private void ensureCapacityInternal(int minimumCapacity) {
          if (minimumCapacity - value.length > 0) {
              value = Arrays.copyOf(value,
                      newCapacity(minimumCapacity));
          }
      }
    
    //计算扩容后长度。minCapacity是期望长度
    private int newCapacity(int minCapacity) {
        // 2*minCapacity + 2
        int newCapacity = (value.length << 1) + 2;
        //如果还不够大直接等于minCapacity
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        //边界判定最大不超过Integer.MAX_VALUE,return
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
    
    • 可传入StringCharSequence、初始化容量、无参四种,除传入容量其他方式都是默认字符串长度 + 16
    • 扩容长度:原数组长度* 2 + 2,如果还是不够,直接扩容到传入的期待值minCapacity。

    3. append()(StringBuilder)

    • 构造函数中介绍了append(),append()有很多重载方法,传入int、double、boolean等,最终都是转成字符拼到了value[]后面,例如"AAAA 1 1.11 false"

    4. insert()(StringBuilder)

    public AbstractStringBuilder insert(int offset, char c) {
          ensureCapacityInternal(count + 1);
          System.arraycopy(value, offset, value, offset + 1, count - offset);
          value[offset] = c;
          count += 1;
          return this;
      }
    
    • insert()append()的区别就是insert()可以指定下标插入字符串,两者源码上区别不大,都是利用System.arraycopy()做的数组拼接。

    5. StringBuilder和StringBuffer

    • 前面说到两者的区别就是线程安全,除了线程优化其他几乎没有区别:
      • StringBuffer在方法上加synchronized保证线程安全。
      • StringBuffer调用toString()时并发的优化:
    //-- StringBuilder.java --
    public String toString() {
        return new String(value, 0, count);
    }
    
    //-- StringBuffer.java --
    private transient char[] toStringCache;
    public synchronized String toString() {
        if (toStringCache == null) {
            toStringCache = Arrays.copyOfRange(value, 0, count);
        }
        return new String(toStringCache, true);
    }
    
    • StringBuilder的toString()创建了一个新的value[],因为不适用于并发,所以没有并发优化。
    • StringBuffer的toString()把value[]提前新建并存在了toStringCache里,任何修改时都会更新toStringCache,并发量大时不会每次调用都new一个新的String。

    相关文章

      网友评论

        本文标题:java.lang.StringBuilder、StringBu

        本文链接:https://www.haomeiwen.com/subject/hqimgctx.html