zoukankan      html  css  js  c++  java
  • StringBuilder&StringBuffer 源码阅读

    StringBuilder 和 StringBuffer

    StringBuilder 和 StringBuffer 都继承了 AbstractStringBuilder 类,所有实际的字符操作都在父类实现,
    主要的区别是 StringBuilder 只是简单的调用父类方法,而 StringBuffer 的写操作都添加了 synchronized 关键字。
    StringBuffer 是线程安全的,而 StringBuilder 不是线程安全的。
    

    AbstractStringBuilder

    • 属性说明
    
    /**
     *  可变的字符序列
     *
     * @author      Michael McCloskey
     * @author      Martin Buchholz
     * @author      Ulf Zibis
     * @since       1.5
     */
    abstract class AbstractStringBuilder implements Appendable, CharSequence {
        /**
         *  用于字符存储的字节数组
         */
        byte[] value;
    
        /**
         *  编码器
         */
        byte coder;
    
        /**
         *  字符总数
         */
        int count;
    
    • 追加字符
        /**
         *  往可变字符序列中追加 boolean 值
         *
         * @param   b   一个 boolean 值
         */
        public AbstractStringBuilder append(boolean b) {
            // 尝试进行扩容
            ensureCapacityInternal(count + (b ? 4 : 5));
            // 读取当前字符数到局部变量表
            int count = this.count;
            // 读取字节数组到局部变量表
            final byte[] val = value;
            // 1)如果是 LATIN1 编码
            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';
                }
                // 2)如果是    UTF16 编码
            } 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;
        }
    
        /**
         *  往可变字符序列中追加单个字符
         *
         * @param   c   单个字符
         */
        @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 值
         *
         * @param   i   一个 int 值
         */
        public AbstractStringBuilder append(int i) {
            final int count = this.count;
            final 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;
        }
    
        /**
         *  往可变字符序列中追加 long 值
         *
         * @param   l   一个 long 值
         */
        public AbstractStringBuilder append(long l) {
            final int count = this.count;
            final 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;
        }
    
        /**
         *  往可变字符序列中追加 float 值
         *
         * @param   f   一个浮点值
         */
        public AbstractStringBuilder append(float f) {
            FloatingDecimal.appendTo(f,this);
            return this;
        }
    
        /**
         *  往可变字符序列中追加 double 值
         *
         * @param   d   一个 double 值
         */
        public AbstractStringBuilder append(double d) {
            FloatingDecimal.appendTo(d,this);
            return this;
        }
    
        /**
         *  往可变字符序列中追加对象
         *
         * @param   obj 一个对象
         */
        public AbstractStringBuilder append(Object obj) {
            return append(String.valueOf(obj));
        }
    
        /**
         *  往可变字符序列中追加字符串
         *
         * @param   str 一个字符串
         */
        public AbstractStringBuilder append(String str) {
            if (str == null) {
                return appendNull();
            }
            final int len = str.length();
            ensureCapacityInternal(count + len);
            putStringAt(count, str);
            count += len;
            return this;
        }
    
        /**
         *  往可变字符序列中追加字符数组
         *
         * @param   str 字符数组
         */
        public AbstractStringBuilder append(char[] str) {
            final int len = str.length;
            ensureCapacityInternal(count + len);
            appendChars(str, 0, len);
            return this;
        }
    
        /**
         *  往可变字符序列中追加字符序列
         *
         * @param s 目标字符序列
         */
        @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());
        }
    
    • 扩容过程
        /**
         *  尝试进行扩容
         */
        private void ensureCapacityInternal(int minimumCapacity) {
            // 读取旧容量 overflow-conscious code
            final int oldCapacity = value.length >> coder;
            // 所需最小容量 > 旧容量
            if (minimumCapacity - oldCapacity > 0) {
                // 扩容并拷贝源字节数组
                value = Arrays.copyOf(value,
                        newCapacity(minimumCapacity) << coder);
            }
        }
    
        /**
         *  返回大于 minCapacity 的最小容量值
         *
         * @param  minCapacity  期望的最小容量
         */
        private int newCapacity(int minCapacity) {
            // overflow-conscious code
            final int oldCapacity = value.length >> coder;
                // 双倍扩容 + 2
                int newCapacity = (oldCapacity << 1) + 2;
                // 扩容后新容量还是 < 期望最小容量,则使用期望最小容量
                if (newCapacity - minCapacity < 0) {
                    newCapacity = minCapacity;
                }
                final int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
                // 一般不会走 hugeCapacity
                return newCapacity <= 0 || SAFE_BOUND - newCapacity < 0 ? hugeCapacity(minCapacity) : newCapacity;
        }
    
        private int hugeCapacity(int minCapacity) {
            final int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
                final int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
                if (UNSAFE_BOUND - minCapacity < 0) { // overflow
                    throw new OutOfMemoryError();
                }
                return minCapacity > SAFE_BOUND
                        ? minCapacity : SAFE_BOUND;
        }
    
    • 插入字符
        /**
         *  在目标索引处插入 boolean 值
         *
         * @param      offset   目标索引
         * @param      b    一个 boolean 值
         */
        public AbstractStringBuilder insert(int offset, boolean b) {
            return insert(offset, String.valueOf(b));
        }
    
        /**
         *  在目标索引 offset 处插入字符串。
         *
         * @param      offset   目标索引
         * @param      str  字符串
         */
        public AbstractStringBuilder insert(int offset, String str) {
            // 校验索引的合法性
            checkOffset(offset, count);
            // 目标字符为 null,则插入 'null'
            if (str == null) {
                str = "null";
            }
            // 计算目标字符长度
            final int len = str.length();
            // 尝试扩容
            ensureCapacityInternal(count + len);
            // 目标索引处及其之后的字符数组集体右移 len 个位置
            shift(offset, len);
            count += len;
            // 插入目标字符串到指定索引 offset 处
            putStringAt(offset, str);
            return this;
        }
    
        /**
         *  通过数组拷贝完成子数组迁移
         *  
         * @param offset    目标索引
         * @param n
         */
        private void shift(int offset, int n) {
            System.arraycopy(value, offset << coder,
                    value, offset + n << coder, count - offset << coder);
        }
    
    • 删除字符
        /**
         *  删除目标索引 start 和 end 之间的所有字符,包括起始不包括结束
         *
         * @param      start    起始索引,包含
         * @param      end  结束索引,不包含
         */
        public AbstractStringBuilder delete(int start, int end) {
            // 从堆内存加载数据到栈局部变量表
            final int count = this.count;
            if (end > count) {
                end = count;
            }
            checkRangeSIOOBE(start, end, count);
            final int len = end - start;
            if (len > 0) {
                // 从 start 索引处开始的子字符数组集体左移 len 个位置
                shift(end, -len);
                this.count = count - len;
            }
            return this;
        }
    
        /**
         *  删除指定索引 index 处的单个字符
         *
         * @param       index   待移除字符的索引
         */
        public AbstractStringBuilder deleteCharAt(int index) {
            checkIndex(index, count);
            shift(index + 1, -1);
            count--;
            return this;
        }
    
    • 截取子字符串
        /**
         *  截取起始索引 start 到结束索引 end 之间的子字符串
         *
         * @param      start    起始索引,包括
         * @param      end  结束索引,不包括
         */
        @Override
        public CharSequence subSequence(int start, int end) {
            return substring(start, end);
        }
    
        /**
         *  截取起始索引 start 到结束索引 end 之间的子字符串
         *
         * @param      start    起始索引,包括
         * @param      end  结束索引,不包括
         */
        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);
        }
    
        /**
         *  从起始索引 start 开始,截取剩余的子字符串
         *
         * @param      start    起始索引,包括
         */
        public String substring(int start) {
            return substring(start, count);
        }
    
  • 相关阅读:
    设计模式 --单例模式
    Neor Profile SQL 中文汉化
    office online server 安装部署整合到到C#项目
    C# 线程池
    WinForm版 屏幕截图
    golang-nsq高性能消息队列
    【Go Time】Go语言里的条件语句else、switch
    【Go Time】Go语言常量定义关键字const
    【Go Time】Go定义变量
    【Go Time】Go语言里的空接口
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10500724.html
Copyright © 2011-2022 走看看