zoukankan      html  css  js  c++  java
  • StringBuffer源码浅析(基于jdk1.8,0_231)

    StringBuffer简介

    • StringBuffer直接继承自AbstractStringBuilder,实现了java.io.Serializable, CharSequence接口,故可序列化,可读的char型序列;
    • 类似于String类,但StringBuffer是线程安全的可变字符串类;
    • StringBuffer具有扩容机制,当需要存储字符的容量不大于当前得value数组长度,不会扩容,否则自动扩成当前容量的2倍+2;
    • 从jdk5开始,新增的StringBuilder基本可StringBuffer一致,但是StringBuilder是非线程安全的,单线程中StringBuilder性能更好;

    StringBuffer UML

    StringBuffer API

    字段

    private transient char[] toStringCache;  //最终保存字符串的数组
    static final long serialVersionUID = 3388685877147921107L;
    private static final java.io.ObjectStreamField[] serialPersistentFields
    
    ------------从AbstractStringBuilder继承的字段----------------
    char[] value;  //存储字符串
    int count;  //记录value数组中存储字符的个数
    

    StringBuffer是可变的字符串类,主要是由于每次对字符串的修改前都会将toStringCache置为null,然后对value存储字符串的数组修改,最后将value中修改后的数组直接复制到toStringCache中,这样我们就保证了StringBuffer是一个可变的字符串数组,每次对同一字符的修改,都在toStringCache指向的同一块内存上。

    所有API

    • 构造函数
    public StringBuffer()
    public StringBuffer(int capacity)
    public StringBuffer(String str)
    public StringBuffer(CharSequence seq)
    

    *直接继承或defalut方法

    public default IntStream chars()
    public default IntStream codePoints() 
    
    • Override或新增的方法
    public synchronized int length()  //得到value的实际存放的字符
    public synchronized int capacity() //得到value的长度(容量长度大于等于长度)
    public synchronized void ensureCapacity(int minimumCapacity) //函数内部实现扩容机制
    public synchronized void trimToSize()  //收缩length变成count
    public synchronized void setLength(int newLength)  //设置value数组长度,当newLength<count,字符串会别截断,newLength>count,多余内存会用''填充;
    public synchronized char charAt(int index) //返回下标字符
    public synchronized void setCharAt(int index, char ch) //更新index位置的字符为新ch
    
    public synchronized int codePointAt(int index)
    public synchronized int codePointBefore(int index) 
    public synchronized int codePointCount(int beginIndex, int endIndex)
    public synchronized int offsetByCodePoints(int index, int codePointOffset)
    public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,int dstBegin)
    
    -------------------append相关方法------------------------------
    public synchronized StringBuffer append(Object obj)
    public synchronized StringBuffer append(String str) 
    public synchronized StringBuffer append(char[] str)
    synchronized StringBuffer append(AbstractStringBuilder asb)
    public synchronized StringBuffer append(CharSequence s)
    public synchronized StringBuffer append(CharSequence s, int start, int end)
    public synchronized StringBuffer append(char[] str, int offset, int len)
    public synchronized StringBuffer append(boolean b) 
    public synchronized StringBuffer append(char c)
    public synchronized StringBuffer append(int i) 
    public synchronized StringBuffer appendCodePoint(int codePoint)
    public synchronized StringBuffer append(long lng) 
    public synchronized StringBuffer append(float f)
    public synchronized StringBuffer append(double d)
    public synchronized StringBuffer append(StringBuffer sb)
    --------------------------delete相关方法-----------------------
    public synchronized StringBuffer delete(int start, int end)
    public synchronized StringBuffer deleteCharAt(int index)
    --------------------------------------------------------------
    public synchronized StringBuffer replace(int start, int end, String str)
    --------------------得到子字符串--------------------------------
    public synchronized String substring(int start) 
    public synchronized CharSequence subSequence(int start, int end)
    public synchronized String substring(int start, int end)
    --------------------insert相关方法
    public synchronized StringBuffer insert(int index, char[] str, int offset,int len)
    public synchronized StringBuffer insert(int offset, Object obj) 
    public synchronized StringBuffer insert(int offset, String str)
    public synchronized StringBuffer insert(int offset, char[] str)
    public StringBuffer insert(int dstOffset, CharSequence s)
    public synchronized StringBuffer insert(int dstOffset, CharSequence s, int start, int end)
    public  StringBuffer insert(int offset, boolean b)
    public synchronized StringBuffer insert(int offset, char c)
    public StringBuffer insert(int offset, int i)
    public StringBuffer insert(int offset, long l)
    public StringBuffer insert(int offset, float f)
    public StringBuffer insert(int offset, double d)
    ---------------------子串匹配方法----------------------------------------
    public int indexOf(String str)  
    public synchronized int indexOf(String str, int fromIndex)
    public int lastIndexOf(String str) 
    public synchronized int lastIndexOf(String str, int fromIndex)
    ---------------------------------------------------------------------------
    public synchronized StringBuffer reverse() //逆序
    public synchronized String toString()
    ------------------序列化-------------------------------------------------
    private synchronized void writeObject(java.io.ObjectOutputStream s)
    private void readObject(java.io.ObjectInputStream s)
    

    StringBuffer 源码

    package java.lang;
    
    import java.util.Arrays;
     public final class StringBuffer
        extends AbstractStringBuilder
        implements java.io.Serializable, CharSequence
    {
    
        //存储字符传的的数组,若修改字符串时该数据就会被清空,只保存数组最后一次修改的值
        private transient char[] toStringCache;
        static final long serialVersionUID = 3388685877147921107L;
        //初始化继承的数组value大小16
        public StringBuffer() {
            super(16);
        }
        //自定义value数组大小
        public StringBuffer(int capacity) {
            super(capacity);
        }
        //构造一个StringBuffer初始化容量为具体的字符产长度+16
        public StringBuffer(String str) {
            super(str.length() + 16);
            append(str);
        }
        //构造一个StringBuffer初始化容量为具体的字符产长度+16
        public StringBuffer(CharSequence seq) {
            this(seq.length() + 16);
            append(seq);
        }
        //返回实际存放的字符数
        @Override
        public synchronized int length() {
            return count;
        }
        // 返回value数组的长度
        @Override
        public synchronized int capacity() {
            return value.length;
        }
        @Override
        public synchronized void ensureCapacity(int minimumCapacity) {
            super.ensureCapacity(minimumCapacity);
        }
        //value收缩为实际含的字符数
        @Override
        public synchronized void trimToSize() {
            super.trimToSize();
        }
        // 重新设置数组长度
        @Override
        public synchronized void setLength(int newLength) {
            toStringCache = null;
            super.setLength(newLength);
        }
        // 返回value数组下标值
        @Override
        public synchronized char charAt(int index) {
            if ((index < 0) || (index >= count))
                throw new StringIndexOutOfBoundsException(index);
            return value[index];
        }
        //返回指定索引字符的Unicode码
        @Override
        public synchronized int codePointAt(int index) {
            return super.codePointAt(index);
        }
    
        // 返回指定索引的前一位索引位置的字符的unicode码 = codePointAt(int index-1)
        @Override
        public synchronized int codePointBefore(int index) {
            return super.codePointBefore(index);
        }
    
        // 计算法从[beginIndex,endIndex)之间共多少unicode码
        @Override
        public synchronized int codePointCount(int beginIndex, int endIndex) {
            return super.codePointCount(beginIndex, endIndex);
        }
        // 
        @Override
        public synchronized int offsetByCodePoints(int index, int codePointOffset) {
            return super.offsetByCodePoints(index, codePointOffset);
        }
        
        @Override
        public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                          int dstBegin)
        {
            super.getChars(srcBegin, srcEnd, dst, dstBegin);
        }
    
        // 先将toStringCache数组清空,在更新value[index]位置的字符
        @Override
        public synchronized void setCharAt(int index, char ch) {
            if ((index < 0) || (index >= count))
                throw new StringIndexOutOfBoundsException(index);
            toStringCache = null;
            value[index] = ch;
        }
        // 先将toStringCache数组清空,在value上追加新的字符串,
        @Override
        public synchronized StringBuffer append(Object obj) {
            toStringCache = null;
            super.append(String.valueOf(obj));
            return this;
        }
        // 先将toStringCache数组清空,在value上追加新的字符串 
        @Override
        public synchronized StringBuffer append(String str) {
            toStringCache = null;
            super.append(str);
            return this;
        }
        //将指定的stringbuffer加入
        public synchronized StringBuffer append(StringBuffer sb) {
            toStringCache = null;
            super.append(sb);
            return this;
        }
      
        @Override
        synchronized StringBuffer append(AbstractStringBuilder asb) {
            toStringCache = null;
            super.append(asb);
            return this;
        }
        @Override
        public synchronized StringBuffer append(CharSequence s) {
            toStringCache = null;
            super.append(s);
            return this;
        }
        @Override
        public synchronized StringBuffer append(char[] str) {
            toStringCache = null;
            super.append(str);
            return this;
        }
    
        @Override
        public synchronized StringBuffer append(char[] str, int offset, int len) {
            toStringCache = null;
            super.append(str, offset, len);
            return this;
        }
    
        @Override
        public synchronized StringBuffer append(boolean b) {
            toStringCache = null;
            super.append(b);
            return this;
        }
    
        @Override
        public synchronized StringBuffer append(char c) {
            toStringCache = null;
            super.append(c);
            return this;
        }
    
        @Override
        public synchronized StringBuffer append(int i) {
            toStringCache = null;
            super.append(i);
            return this;
        }
    
        /**
         * @since 1.5
         */
        @Override
        public synchronized StringBuffer appendCodePoint(int codePoint) {
            toStringCache = null;
            super.appendCodePoint(codePoint);
            return this;
        }
    
        @Override
        public synchronized StringBuffer append(long lng) {
            toStringCache = null;
            super.append(lng);
            return this;
        }
    
        @Override
        public synchronized StringBuffer append(float f) {
            toStringCache = null;
            super.append(f);
            return this;
        }
    
        @Override
        public synchronized StringBuffer append(double d) {
            toStringCache = null;
            super.append(d);
            return this;
        }
        @Override
        public synchronized StringBuffer delete(int start, int end) {
            toStringCache = null;
            super.delete(start, end);
            return this;
        }
    
        @Override
        public synchronized StringBuffer deleteCharAt(int index) {
            toStringCache = null;
            super.deleteCharAt(index);
            return this;
        }
        @Override
        public synchronized StringBuffer replace(int start, int end, String str) {
            toStringCache = null;
            super.replace(start, end, str);
            return this;
        }
        @Override
        public synchronized String substring(int start) {
            return substring(start, count);
        }
    
        @Override
        public synchronized CharSequence subSequence(int start, int end) {
            return super.substring(start, end);
        }
    
        @Override
        public synchronized String substring(int start, int end) {
            return super.substring(start, end);
        }
    
        @Override
        public synchronized StringBuffer insert(int index, char[] str, int offset,
                                                int len)
        {
            toStringCache = null;
            super.insert(index, str, offset, len);
            return this;
        }
    
        @Override
        public synchronized StringBuffer insert(int offset, Object obj) {
            toStringCache = null;
            super.insert(offset, String.valueOf(obj));
            return this;
        }
    
        @Override
        public synchronized StringBuffer insert(int offset, String str) {
            toStringCache = null;
            super.insert(offset, str);
            return this;
        }
        @Override
        public synchronized StringBuffer insert(int offset, char[] str) {
            toStringCache = null;
            super.insert(offset, str);
            return this;
        }
    
        @Override
        public StringBuffer insert(int dstOffset, CharSequence s) {
            // Note, synchronization achieved via invocations of other StringBuffer methods
            // after narrowing of s to specific type
            // Ditto for toStringCache clearing
            super.insert(dstOffset, s);
            return this;
        }
    
        @Override
        public synchronized StringBuffer insert(int dstOffset, CharSequence s,
                int start, int end)
        {
            toStringCache = null;
            super.insert(dstOffset, s, start, end);
            return this;
        }
    
        @Override
        public  StringBuffer insert(int offset, boolean b) {
            // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
            // after conversion of b to String by super class method
            // Ditto for toStringCache clearing
            super.insert(offset, b);
            return this;
        }
        @Override
        public synchronized StringBuffer insert(int offset, char c) {
            toStringCache = null;
            super.insert(offset, c);
            return this;
        }
    
        @Override
        public StringBuffer insert(int offset, int i) {
            // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
            // after conversion of i to String by super class method
            // Ditto for toStringCache clearing
            super.insert(offset, i);
            return this;
        }
    
        /**
         * @throws StringIndexOutOfBoundsException {@inheritDoc}
         */
        @Override
        public StringBuffer insert(int offset, long l) {
            // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
            // after conversion of l to String by super class method
            // Ditto for toStringCache clearing
            super.insert(offset, l);
            return this;
        }
    
        /**
         * @throws StringIndexOutOfBoundsException {@inheritDoc}
         */
        @Override
        public StringBuffer insert(int offset, float f) {
            // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
            // after conversion of f to String by super class method
            // Ditto for toStringCache clearing
            super.insert(offset, f);
            return this;
        }
    
        /**
         * @throws StringIndexOutOfBoundsException {@inheritDoc}
         */
        @Override
        public StringBuffer insert(int offset, double d) {
            // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
            // after conversion of d to String by super class method
            // Ditto for toStringCache clearing
            super.insert(offset, d);
            return this;
        }
    
        /**
         * @since      1.4
         */
        @Override
        public int indexOf(String str) {
            // Note, synchronization achieved via invocations of other StringBuffer methods
            return super.indexOf(str);
        }
    
        /**
         * @since      1.4
         */
        @Override
        public synchronized int indexOf(String str, int fromIndex) {
            return super.indexOf(str, fromIndex);
        }
    
        /**
         * @since      1.4
         */
        @Override
        public int lastIndexOf(String str) {
            // Note, synchronization achieved via invocations of other StringBuffer methods
            return lastIndexOf(str, count);
        }
    
        /**
         * @since      1.4
         */
        @Override
        public synchronized int lastIndexOf(String str, int fromIndex) {
            return super.lastIndexOf(str, fromIndex);
        }
    
        /**
         * @since   JDK1.0.2
         */
        @Override
        public synchronized StringBuffer reverse() {
            toStringCache = null;
            super.reverse();
            return this;
        }
        // toStirng 方法将value中保存的字符拷贝到toStringCache,保障了对同一个示例的操作,都在同一块内存,即保证了StringBuffer为可变字符串类
        @Override
        public synchronized String toString() {
            if (toStringCache == null) {
                toStringCache = Arrays.copyOfRange(value, 0, count);
            }
            return new String(toStringCache, true);
        }
    
        private static final java.io.ObjectStreamField[] serialPersistentFields =
        {
            new java.io.ObjectStreamField("value", char[].class),
            new java.io.ObjectStreamField("count", Integer.TYPE),
            new java.io.ObjectStreamField("shared", Boolean.TYPE),
        };
    
        private synchronized void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
            java.io.ObjectOutputStream.PutField fields = s.putFields();
            fields.put("value", value);
            fields.put("count", count);
            fields.put("shared", false);
            s.writeFields();
        }
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            java.io.ObjectInputStream.GetField fields = s.readFields();
            value = (char[])fields.get("value", null);
            count = fields.get("count", 0);
        }
    }
    

    StringBuffer示例

    package commonclass;
    
    
    import java.util.stream.Collectors;
    
    public class StringBufferTest {
        public static void main(String[] args) {
            /**
             * StringBuffer构造函数
             */
            StringBuffer stringBuffer1 = new StringBuffer();
            StringBuffer stringBuffer2 = new StringBuffer(32);
            StringBuffer stringBuffer3 = new StringBuffer("helloworld");
            StringBuffer stringBuffer4 = new StringBuffer(new CharSequence() {
                private  char[] myString = "AHPU&SEU".toCharArray();
                @Override
                public int length() {
                    return myString.length;
                }
    
                @Override
                public char charAt(int index) {
                    if (index < 0 || index > myString.length)
                        throw new IndexOutOfBoundsException();
                    return myString[index];
                }
    
                @Override
                public CharSequence subSequence(int start, int end) {
                    return new java.lang.String(myString, start, end - start);
                }
            });
    
            /**
             * append
             */
            stringBuffer1  = stringBuffer1.append("hi java");
            System.out.println(stringBuffer1.length()); //7
            System.out.println(stringBuffer1.capacity()); //16
            stringBuffer1.append(1);
            stringBuffer1.append('2');
            stringBuffer1.append(3.14F);
            stringBuffer1.append(2.78D);
            stringBuffer1.append(true);
            stringBuffer1.append("arrays".toCharArray());
            stringBuffer1.append(2000L);
            stringBuffer1.append("string");
            stringBuffer1.append(stringBuffer3);
            stringBuffer1.append(stringBuffer4);
            stringBuffer1.append(new Object());
            System.out.println(stringBuffer1);
            System.out.println(stringBuffer1.length());
            System.out.println(stringBuffer1.capacity());
            stringBuffer1 = null;
            System.out.println(stringBuffer1);
    
            /**
             * insert
             */
    
            stringBuffer3 = stringBuffer3.insert(0,'h');
            System.out.println(stringBuffer3);
            stringBuffer3 = stringBuffer3.insert(1,1);
            System.out.println(stringBuffer3);
            stringBuffer3  = stringBuffer3.insert(2,2000L);
            System.out.println(stringBuffer3);
            stringBuffer3.insert(0,3.14F);
            System.out.println(stringBuffer3);
            stringBuffer3.insert(0,false);
            System.out.println(stringBuffer3);
            stringBuffer3.insert(0,"mystring".toCharArray());
            System.out.println(stringBuffer3);
            stringBuffer3.insert(0,stringBuffer4);
            System.out.println(stringBuffer3);
            stringBuffer3.insert(0,new Object());
            System.out.println(stringBuffer3);
            stringBuffer3.insert(0,"zyxzyx".toCharArray(),0,3);
            System.out.println(stringBuffer3);
            stringBuffer3.insert(0,stringBuffer4,4,5);
            System.out.println(stringBuffer3);
    
            /**
             * delete
             */
            CharSequence s3sub = stringBuffer3.subSequence(stringBuffer3.length()-10,stringBuffer3.length());
            System.out.println(s3sub.toString());
            stringBuffer3.deleteCharAt(0);
            System.out.println(stringBuffer3);
            /**
             * 查 改
             */
            stringBuffer3.setCharAt(0,'Z');
            System.out.println(stringBuffer3);
            int len = stringBuffer3.length();
            System.out.println(len);
            int cap = stringBuffer3.capacity();
            System.out.println(cap);
            stringBuffer3.trimToSize();
            System.out.println(stringBuffer3.capacity() + " " + stringBuffer3.length());
            char ch = stringBuffer3.charAt(0);
            System.out.println(ch);
            String  string = stringBuffer3.substring(stringBuffer3.length()-"helloworld".length());
            System.out.println(string);
            String str = stringBuffer3.substring(0,3);
            System.out.println(str);
            stringBuffer3.reverse();
            System.out.println(stringBuffer3);
            stringBuffer3.reverse();
            System.out.println(stringBuffer3);
            int index = stringBuffer3.indexOf("helloworld");
            System.out.println(index);
            int index1 = stringBuffer3.indexOf("helloworle");
            System.out.println(index1);
            int index2 = stringBuffer3.indexOf("hello",10);
            System.out.println(index2);
            stringBuffer3.replace(0,2,"ahpu");
            System.out.println(stringBuffer3);
    
    //        stringBuffer3.setLength(100);
    //        System.out.println(stringBuffer3.charAt(99));
            System.out.println(stringBuffer3.length());
            int lindex = stringBuffer3.lastIndexOf("helloworld");
            System.out.println(lindex);
            index = stringBuffer3.indexOf("helloworld");
            System.out.println(index);
            char[] dst = new char[50];
            System.out.println(stringBuffer3.length());
            System.out.println(stringBuffer3);
            stringBuffer3.trimToSize();
            System.out.println(stringBuffer3.length());
            stringBuffer3.getChars(61,stringBuffer3.length(),dst,0);
            System.out.println(dst);
            /**
             *
             */
            int unicode =  stringBuffer3.codePointAt(1);
            System.out.println(unicode);
    
            int unicode1 = stringBuffer3.codePointBefore(1);
            System.out.println(unicode1);
            System.out.println(stringBuffer3.length() + " " + stringBuffer3.capacity());
            // 这个方法还真不知道有啥用处
            int unicode2 = stringBuffer3.offsetByCodePoints(10,-2);
            System.out.println(unicode2);
        }
    }
    
    
    • 结果
    7
    16
    hi java123.142.78truearrays2000stringhelloworldAHPU&SEUjava.lang.Object@1b6d3586
    80
    142
    null
    hhelloworld
    h1helloworld
    h12000helloworld
    3.14h12000helloworld
    false3.14h12000helloworld
    mystringfalse3.14h12000helloworld
    AHPU&SEUmystringfalse3.14h12000helloworld
    java.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    &zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    helloworld
    zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    Zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    69
    110
    69 69
    Z
    helloworld
    Zyx
    dlrowolleh00021h41.3eslafgnirtsymUES&UPHAc7164554@tcejbO.gnal.avajxyZ
    Zyxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    59
    -1
    59
    ahpuxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    71
    61
    61
    71
    ahpuxjava.lang.Object@4554617cAHPU&SEUmystringfalse3.14h12000helloworld
    71
    helloworld                                        
    104
    97
    71 71
    8
    
    

    面试session

    • StringBuffer StringBuilder String 的异同和使用场景?
      (1) StringBuffer是线程安全的,StringBuilder在单线程是StringBuilder的替代品,二者方法基本一致,但是StringBuilder是线程不安全的,二者都是可变字符串类;
      (2) String是不可变字符串类;
  • 相关阅读:
    VS调试技巧
    Git 分支
    WPF:如何高速更新Model中的属性
    Redis-4.0.11集群配置
    大压力下Redis参数调整要点
    统计UPD丢包工具
    查看Redis集群所有节点内存工具
    Redis集群命令行部署工具
    查看Redis集群主从对应关系工具
    Redis集群master选举时长测试
  • 原文地址:https://www.cnblogs.com/ahpucd/p/13460044.html
Copyright © 2011-2022 走看看