JDK源码之AbstractStringBuilder类分析

一 概述

二 实现接口

AbstractStringBuilder实现了两个接口:

  1. Appendable
    • 概述:
      Appendable的实现类的对象可以附加字符序列和值.
      要追加的字符应该是Unicode字符表示中描述的有效Unicode字符。注意,补充字符可能由多个16位字符值组成。
      对于多线程访问不一定是安全的。线程安全是扩展和实现这个接口的类的职责。
      IO流操作的写类基本都实现了这个接口,比如BufferedWriter, CharArrayWriter, CharBuffer, FileWriter等,还有StringBuffer和StringBuild也实现了这个接口
    • 接口定义的方法:
    /**
     * 添加CharSequence序列到当前对象,并返回当前对象
     */
    Appendable append(CharSequence csq) throws IOException;

    /**
     * 添加CharSequence序列参数的子序列,按照参数进行分割,到当前对象
     */
    Appendable append(CharSequence csq, int start, int end) throws IOException;

    /**
     * 添加char值到当前对象
     */
    Appendable append(char c) throws IOException;
  1. CharSequence

    这个接口就不多说了,表示char 值的一个可读序列(有序集合),

三 源码解析

1 属性

    // 表示AbstractStringBuilder的值,可变的byte数组,jdk9之前是char数组
    byte[] value;

    // coder编码值,jdk9之后添加的编码标识,和String的编码coder是一样的
    byte coder;

    // 当前字符串已经使用的byte数组中的长度,增删改查的同时需要维护这个属性值
    int count;

    //空byte数组,用于无参构造器初始化,jdk9之后新增的
    private static final byte[] EMPTYVALUE = new byte[0];

    // 能创建数组长度的最大值
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

2 构造器

    /**
     * 无参构造器,vlaue默认赋值为一个长度为0的byte数组
     */
    AbstractStringBuilder() {
        value = EMPTYVALUE;
    }

    /**
     * 根据参数创建指定长度的byte数组
     */
    AbstractStringBuilder(int capacity) {
        // 根据是否压缩标识创建单字节或者双字节存储
        if (COMPACT_STRINGS) {
            value = new byte[capacity];
            coder = LATIN1;
        } else {
            value = StringUTF16.newBytesFor(capacity);//将capacity << 1 ,即创建capacity乘以2的大小byte数组
            coder = UTF16;
        }
    }

3 基本api

    //jdk11新增方法,比较大小
    int compareTo(AbstractStringBuilder another) {
        if (this == another) {
            return 0;
        }

        byte val1[] = value;
        byte val2[] = another.value;
        int count1 = this.count;
        int count2 = another.count;

        if (coder == another.coder) {
            return isLatin1() ? StringLatin1.compareTo(val1, val2, count1, count2)
                    : StringUTF16.compareTo(val1, val2, count1, count2);
        }
        return isLatin1() ? StringLatin1.compareToUTF16(val1, val2, count1, count2)
                : StringUTF16.compareToLatin1(val1, val2, count1, count2);
    }

    //返回当前字符串实际的长度
    @Override
    public int length() {
        return count;
    }

    //返回当前字符所占用byte数组的长度, >= length()
    public int capacity() {
        return value.length >> coder;
    }

    //确保当前value的数组长度至少等于指定的参数
    public void ensureCapacity(int minimumCapacity) {
        if (minimumCapacity > 0) {
            ensureCapacityInternal(minimumCapacity);
        }
    }

    private void ensureCapacityInternal(int minimumCapacity) {
        // 防止append的时候数组越界
        int oldCapacity = value.length >> coder;
        if (minimumCapacity - oldCapacity > 0) { //参数 > 当前byte数组长度
            // 创建新长度大小的byte数组,并将value值进行copy,重新赋值给当前value
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity) << coder);
        }
    }

    /**
     * 判断给定参数是否溢出或者小于0,并返回合理的数组长度
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = value.length >> coder;
        int newCapacity = (oldCapacity << 1) + 2;
        //每次扩容,最少扩大原来的2倍+2
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
        // 验证扩容值是否溢出
        return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0)
                ? hugeCapacity(minCapacity)
                : newCapacity;
    }

    //越界检查.是否超过最大值
    private int hugeCapacity(int minCapacity) {
        int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
        int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
        if (UNSAFE_BOUND - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > SAFE_BOUND)
                ? minCapacity : SAFE_BOUND;
    }

    //如果编码是Latin,则byte数组扩容为原来两倍,并将原有的值按双字节存储,编码改为UTF16
    private void inflate() {
        if (!isLatin1()) {
            return;
        }
        byte[] buf = StringUTF16.newBytesFor(value.length);
        StringLatin1.inflate(value, 0, buf, 0, count);
        this.value = buf;
        this.coder = UTF16;
    }

    //如果value数组的容量有多余的,那么就把多余的全部都释放掉
    public void trimToSize() {
        int length = count << coder; //实际使用了的长度
        if (length < value.length) { // byte数组长度
            value = Arrays.copyOf(value, length);
        }
    }

    /**
     * 强制增大实际长度count的大小,容量如果不够就用 expandCapacity()扩大;
     * 将扩大的部分全部用’\0’(ASCII码中的null)来初始化
     */
    public void setLength(int newLength) {
        if (newLength < 0) {
            throw new StringIndexOutOfBoundsException(newLength);
        }
        ensureCapacityInternal(newLength);
        if (count < newLength) {
            if (isLatin1()) {
                //使用null填充
                StringLatin1.fillNull(value, count, newLength);
            } else {
                StringUTF16.fillNull(value, count, newLength);
            }
        }
        count = newLength;
    }

    // 抽象方法,需要子类自己实现
    @Override
    public abstract String toString();

4 增(append)

    /**
     * 添加Object,实际是把对象转为String,调用添加String方法
     */
    public AbstractStringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    /**
     * 添加String
     */
    public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        int len = str.length();
        //对 byte数组扩容,确保长度大于 count+len
        ensureCapacityInternal(count + len);
        //讲str追加到byte数组中
        putStringAt(count, str);
        count += len; //修改实际占用长度
        return this;
    }

    //添加 StringBuffer
    public AbstractStringBuilder append(StringBuffer sb) {
        return this.append((AbstractStringBuilder)sb);
    }

    /**
     * jdk1.8新加的方法,逻辑跟添加String是一样的
     */
    AbstractStringBuilder append(AbstractStringBuilder asb) {
        if (asb == null) {
            return appendNull();
        }
        int len = asb.length();
        ensureCapacityInternal(count + len);
        if (getCoder() != asb.getCoder()) {
            inflate();
        }
        asb.getBytes(value, count, coder);
        count += len;
        return this;
    }

    // 添加 CharSequence,实现Appendable接口的方法
    @Override
    public AbstractStringBuilder append(CharSequence s) {
        if (s == null) {
            return appendNull();
        }
        if (s instanceof String) {
            return this.append((String)s);
        }
        if (s instanceof AbstractStringBuilder) {
            return this.append((AbstractStringBuilder)s);
        }
        return this.append(s, 0, s.length());
    }

    // 添加字符串 "null"
    private AbstractStringBuilder appendNull() {
        ensureCapacityInternal(count + 4);
        int count = this.count;
        byte[] val = this.value;
        if (isLatin1()) {
            val[count++] = 'n';
            val[count++] = 'u';
            val[count++] = 'l';
            val[count++] = 'l';
        } else {
            count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
        }
        this.count = count;
        return this;
    }


    //指定位置添加 s
    @Override
    public AbstractStringBuilder append(CharSequence s, int start, int end) {
        if (s == null) {
            s = "null";
        }
        checkRange(start, end, s.length());
        int len = end - start;
        ensureCapacityInternal(count + len);
        appendChars(s, start, end);
        return this;
    }

    // 添加插入数组
    public AbstractStringBuilder append(char[] str) {
        int len = str.length;
        ensureCapacityInternal(count + len);
        appendChars(str, 0, len);
        return this;
    }

    /**
     * 添加插入数组, 指定开始位置和添加的长度
     */
    public AbstractStringBuilder append(char str[], int offset, int len) {
        int end = offset + len;
        checkRange(offset, end, str.length);
        ensureCapacityInternal(count + len);
        appendChars(str, offset, end);
        return this;
    }

    // 添加 'true' 或者 'false'
    public AbstractStringBuilder append(boolean b) {
        ensureCapacityInternal(count + (b ? 4 : 5));
        int count = this.count;
        byte[] val = this.value;
        if (isLatin1()) {
            if (b) {
                val[count++] = 't';
                val[count++] = 'r';
                val[count++] = 'u';
                val[count++] = 'e';
            } else {
                val[count++] = 'f';
                val[count++] = 'a';
                val[count++] = 'l';
                val[count++] = 's';
                val[count++] = 'e';
            }
        } else {
            if (b) {
                count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
            } else {
                count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
            }
        }
        this.count = count;
        return this;
    }

    //添加unicode代码点
    public AbstractStringBuilder appendCodePoint(int codePoint) {
        if (Character.isBmpCodePoint(codePoint)) {
            return append((char)codePoint);
        }
        return append(Character.toChars(codePoint));
    }
    // 添加 char
    @Override
    public AbstractStringBuilder append(char c) {
        ensureCapacityInternal(count + 1);
        if (isLatin1() && StringLatin1.canEncode(c)) {
            value[count++] = (byte)c;
        } else {
            if (isLatin1()) {
                inflate();
            }
            StringUTF16.putCharSB(value, count++, c);
        }
        return this;
    }

    // 添加 int,以下都是添加number
    public AbstractStringBuilder append(int i) {
        int count = this.count;
        int spaceNeeded = count + Integer.stringSize(i);
        ensureCapacityInternal(spaceNeeded);
        if (isLatin1()) {
            Integer.getChars(i, spaceNeeded, value);
        } else {
            StringUTF16.getChars(i, count, spaceNeeded, value);
        }
        this.count = spaceNeeded;
        return this;
    }

    public AbstractStringBuilder append(long l) {
        int count = this.count;
        int spaceNeeded = count + Long.stringSize(l);
        ensureCapacityInternal(spaceNeeded);
        if (isLatin1()) {
            Long.getChars(l, spaceNeeded, value);
        } else {
            StringUTF16.getChars(l, count, spaceNeeded, value);
        }
        this.count = spaceNeeded;
        return this;
    }

    public AbstractStringBuilder append(float f) {
        FloatingDecimal.appendTo(f,this);
        return this;
    }

    public AbstractStringBuilder append(double d) {
        FloatingDecimal.appendTo(d,this);
        return this;
    }

    /**
     * 在 index位置插入 char数组的一部分,这部分从是[ offset,offset + len )
     */
    public AbstractStringBuilder insert(int index, char[] str, int offset,
                                        int len)
    {
        checkOffset(index, count);
        checkRangeSIOOBE(offset, offset + len, str.length);
        ensureCapacityInternal(count + len);
        shift(index, len);
        count += len;
        putCharsAt(index, str, offset, offset + len);
        return this;
    }

    /**
     * 在 offset位置,插入 obj,其他像int,boolean 都是类似的用String.valueOf转然后调用插入String方法
     */
    public AbstractStringBuilder insert(int offset, Object obj) {
        return insert(offset, String.valueOf(obj));
    }

    public AbstractStringBuilder insert(int offset, String str) {
        checkOffset(offset, count);
        if (str == null) {
            str = "null";
        }
        int len = str.length();
        ensureCapacityInternal(count + len);
        shift(offset, len);
        count += len;
        putStringAt(offset, str);
        return this;
    }

5 删

    /**
     * 删除指定位置的字符
     */
    public AbstractStringBuilder delete(int start, int end) {
        int count = this.count;
        if (end > count) {
            end = count;
        }
        checkRangeSIOOBE(start, end, count);
        int len = end - start;
        if (len > 0) {
            shift(end, -len); //调用System.arraycopy 方法
            this.count = count - len;
        }
        return this;
    }

    /**
     * 删除指定位置的字符
     */
    public AbstractStringBuilder deleteCharAt(int index) {
        checkIndex(index, count);
        shift(index + 1, -1); //删除 index index+1 位置的字符
        count--;
        return this;
    }
    // 将value从offset开始复制 count-offset个值,从 offset+n 开始重新赋值给value, 即删减 n 个字符
    private void shift(int offset, int n) {
        System.arraycopy(value, offset << coder,
                value, (offset + n) << coder, (count - offset) << coder);
    }

6 改

    /**
     * 用字符串str替换掉value[]数组的[start,end)部分
     */
    public AbstractStringBuilder replace(int start, int end, String str) {
        int count = this.count;
        if (end > count) {
            end = count;
        }
        checkRangeSIOOBE(start, end, count);
        int len = str.length();
        int newCount = count + len - (end - start);
        ensureCapacityInternal(newCount);//扩容
        shift(end, newCount - count);// 从指定end处开始,删除或者增加 newCount - count个值
        this.count = newCount;
        putStringAt(start, str); //从start开始添加字符
        return this;
    }

    //截取子字符串
    public String substring(int start) {
        return substring(start, count);
    }

    public String substring(int start, int end) {
        checkRangeSIOOBE(start, end, count);
        if (isLatin1()) {
            return StringLatin1.newString(value, start, end - start);
        }
        return StringUTF16.newString(value, start, end - start);
    }

    /**
     * 在指定index位置设置 char值
     */
    public void setCharAt(int index, char ch) {
        checkIndex(index, count);
        if (isLatin1() && StringLatin1.canEncode(ch)) {
            value[index] = (byte)ch;
        } else {
            if (isLatin1()) {
                inflate();
            }
            StringUTF16.putCharSB(value, index, ch);
        }
    }

    /**
     * 将value给倒序存放(注意改变的就是本value,而不是创建了一个新的AbstractStringBuilder然后value为倒序)
     */
    public AbstractStringBuilder reverse() {
        byte[] val = this.value;
        int count = this.count;
        int coder = this.coder;
        int n = count - 1;
        if (COMPACT_STRINGS && coder == LATIN1) {
            for (int j = (n-1) >> 1; j >= 0; j--) {
                int k = n - j;
                byte cj = val[j];
                val[j] = val[k];
                val[k] = cj;
            }
        } else {
            StringUTF16.reverse(val, count);
        }
        return this;
    }

7 查

    /**
     * 获取下标为index的char字符
     */
    @Override
    public char charAt(int index) {
        checkIndex(index, count);
        if (isLatin1()) {
            return (char)(value[index] & 0xff);
        }
        return StringUTF16.charAt(value, index);
    }

    /**
     * 获取index位置的unicode代码单位
     */
    public int codePointAt(int index) {
        int count = this.count;
        byte[] value = this.value;
        checkIndex(index, count);
        if (isLatin1()) {
            return value[index] & 0xff;
        }
        return StringUTF16.codePointAtSB(value, index, count);
    }

    /**
     * 将value[]的 [srcBegin, srcEnd) 拷贝到 dst[]数组的desBegin开始处
     */
    public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
    {
        checkRangeSIOOBE(srcBegin, srcEnd, count);  // compatible to old version
        int n = srcEnd - srcBegin;
        checkRange(dstBegin, dstBegin + n, dst.length);
        if (isLatin1()) {
            StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);
        } else {
            StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);
        }
    }

    //在value[]中找字符串str,若能找到,返回第一个字符串的第一个字符的下标
    public int indexOf(String str) {
        return indexOf(str, 0);
    }

    //从fromIndex开始,在value[]中找字符串str,若能找到,返回第一个字符串的第一个字符的下标
    public int indexOf(String str, int fromIndex) {
        return String.indexOf(value, coder, count, str, fromIndex);
    }

    // 从后面往前找
    public int lastIndexOf(String str) {
        return lastIndexOf(str, count);
    }

    // 从后面往前找
    public int lastIndexOf(String str, int fromIndex) {
        return String.lastIndexOf(value, coder, count, str, fromIndex);
    }

    /**
     * jdk9 新增方法,获取int流
     */
    @Override
    public IntStream chars() {
        return StreamSupport.intStream(
                () -> {
                    byte[] val = this.value;
                    int count = this.count;
                    byte coder = this.coder;
                    return coder == LATIN1
                            ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
                            : new StringUTF16.CharsSpliterator(val, 0, count, 0);
                },
                Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
                false);
    }

    /**
     * jdk9 新增方法,获取unicode代码点int 流
     */
    @Override
    public IntStream codePoints() {
        return StreamSupport.intStream(
                () -> {
                    byte[] val = this.value;
                    int count = this.count;
                    byte coder = this.coder;
                    return coder == LATIN1
                            ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
                            : new StringUTF16.CodePointsSpliterator(val, 0, count, 0);
                },
                Spliterator.ORDERED,
                false);
    }

四 总结

AbstractStringBuilder就是 可变 字符序列的一个纲领
它规定了可变字符序列应该有的行为
比如 添加字符/删除字符/更新字符/获取字符
因为可变,所以对于可变的支持,自然是必不可少的
另外,他作为String在很多方面的一个替代,必然也是提供了String的一些功能方法
否则与String API 变化巨大 也是毫无意义
因为毕竟本身就是为了描述字符序列
所以对于AbstractStringBuilder 只需要彻底理解了他作为 可变字符序列的标准接口即可
接口的两个实现StringBuffer和StringBuild大部分的功能也都是调用的父类方法!

posted @ 2020-01-05 21:33  侯小厨  阅读(760)  评论(0编辑  收藏  举报
Fork me on Gitee