zoukankan      html  css  js  c++  java
  • 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()扩大;
         * 将扩大的部分全部用’’(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大部分的功能也都是调用的父类方法!

  • 相关阅读:
    单例模式
    Curator Zookeeper分布式锁
    LruCache算法原理及实现
    lombok 简化java代码注解
    Oracle客户端工具出现“Cannot access NLS data files or invalid environment specified”错误的解决办法
    解决mysql Table ‘xxx’ is marked as crashed and should be repaired的问题。
    Redis 3.0 Cluster集群配置
    分布式锁的三种实现方式
    maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令
    How to Use Convolutional Neural Networks for Time Series Classification
  • 原文地址:https://www.cnblogs.com/houzheng/p/12153734.html
Copyright © 2011-2022 走看看