美文网首页java成长笔记
StringBuilder和StringBuffer

StringBuilder和StringBuffer

作者: G_uest | 来源:发表于2019-08-14 20:07 被阅读0次

    区别

    StringBuffer:jdk 1.0出现,线程安全,效率低

    StringBuilder: jdk 1.5出现,线程不安全,效率高

    StringBuilder怎么实现的线程安全

    StringBuilder 中的大量方法都使用 synchronized 修饰,来实现线程安全,就是因为这样速度才会慢。
    二者的实现几乎没什么区别,具有相同的父类和接口,具体实现方法都由父类完成。

    StringBuffer 部分源码

    public final class StringBuffer
        extends AbstractStringBuilder
        implements java.io.Serializable, CharSequence
    {
        // toString返回的最后一个值的缓存。每当修改StringBuffer时清除。
        private transient char[] toStringCache;
    
        // 默认初始化容量为16个字符
        public StringBuffer() {
            super(16);
        }
        
        // 如果构造方法中传入了一个字符串,长度为字符串长度加16
        public StringBuffer(String str) {
            super(str.length() + 16);
            append(str);
        }
        
        // 被 synchronized 修饰方法还有很多,不再一一列举
        @Override
        public synchronized StringBuffer append(String str) {
            // StringBuffer将会被修改,清除 toStringCache
            toStringCache = null;
            super.append(str);
            return this;
        }
        
        // 重写toString方法
        @Override
        public synchronized String toString() {
            if (toStringCache == null) {
                toStringCache = Arrays.copyOfRange(value, 0, count);
            }
            return new String(toStringCache, true);
        }
    }
    
    
    

    StringBuilder 部分源码

    public final class StringBuilder
        extends AbstractStringBuilder
        implements java.io.Serializable, CharSequence
    {
        // 默认初始化容量为16个字符
        public StringBuilder() {
            super(16);
        }
        
        // 如果构造方法中传入了一个字符串,长度为字符串长度加16
        public StringBuilder(String str) {
            super(str.length() + 16);
            append(str);
        }
        
        // 添加字符串方法
        @Override
        public StringBuilder append(String str) {
            super.append(str);
            return this;
        }
        
        // toString 方法
        @Override
        public String toString() {
            // 创建一个副本,不要共享数组
            return new String(value, 0, count);
        }
    }
    

    扩容方法

    先扩充为 原长度 * 2 + 2 的长度,然后判断扩充后的长度是否大于StringBuilder拼接字符串后的长度(新添加的+已有的长度),如果小于的话,就执行newCapacity = StringBuilder(StringBuilder为拼接后字符串的长度)。如果newCapacity<0说明数组长度已经超出了范围,这时调用hugeCapacity方法,执行newCapacity = Integer.MAX_VALUE
    AbstractStringBuilder 部分源码

    // 用于字符存储。
    char[] value;
    
    // 数组最大长度
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
    // 扩容方法
    private int newCapacity(int minCapacity) {
        // 先扩充为 原长度 * 2 + 2 的长度
        int newCapacity = (value.length << 1) + 2;
        // 判断扩充后的长度是否大于StringBuilder拼接字符串后的长度
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
            ? hugeCapacity(minCapacity)
            : newCapacity;
    }
    
    // 数组再次扩容,但是长度不能超出int范围
    private int hugeCapacity(int minCapacity) {
        if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE)
            ? minCapacity : MAX_ARRAY_SIZE;
    }
    

    相关文章

      网友评论

        本文标题:StringBuilder和StringBuffer

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