美文网首页程序员
这份JDK源码解析,建议反复观看,写的真的跟详细了!

这份JDK源码解析,建议反复观看,写的真的跟详细了!

作者: 程序员伟杰 | 来源:发表于2020-07-21 13:22 被阅读0次

    1. 概述

    这个抽象类是StringBuilder和StringBuffer的直接父类,实现了两个接口分别是Appendable, CharSequence

    CharSequence是一个字符序列的接口,主要提供了一下的方法

    该接口规定了需要实现该字符序列的长度:length();
    可以取得下标为index的的字符:charAt(int index);
    可以得到该字符序列的一个子字符序列: subSequence(int start, int end);
    重写了父类Object的toString():toString();
    Appendable 定义添加的规则

    append(CharSequence csq) throws IOException:如何添加一个字符序列
    append(CharSequence csq, int start, int end) throws IOException:如何添加一个字符序列的一部分
    append(char c) throws IOException:如何添加一个字符

    2.类图

    3.属性

    char[] value; 记录字符的空间
    int count; char数组中 实际字符的数量

    4.构造方法

    默认构造方法AbstractStringBuilder()

    AbstractStringBuilder(int capacity)

    根据传入的参数初始化char数组空间

    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }
    

    5.返回长度/大小

    length()

    public int length() {
            return count;
    }
    

    capacity()

    public int capacity() {
            return value.length;
    }
    

    length()返回的是char数组中实际字符的个数

    capacity返回的是数组的空间大小

    6.扩容

    ensureCapacity(int minimumCapacity)

            public void ensureCapacity(int minimumCapacity) {
            if (minimumCapacity > 0)
                ensureCapacityInternal(minimumCapacity);
        }
            private void ensureCapacityInternal(int minimumCapacity) {
            // overflow-conscious code
            if (minimumCapacity - value.length > 0)//传入的参数大于现在数组的空间则扩容
                expandCapacity(minimumCapacity);
        }
            void expandCapacity(int minimumCapacity) {
            int newCapacity = value.length * 2 + 2;//新空间为(原来空间+1)*2
            if (newCapacity - minimumCapacity < 0)//若心的空间比传入的参数小,则新空间为传入的参数
                newCapacity = minimumCapacity;
            if (newCapacity < 0) {//若新空间小于0 // int越界后可能出现小于0的情况
                if (minimumCapacity < 0) // 传入的参数也小于0 则抛出异常
                    throw new OutOfMemoryError();
                newCapacity = Integer.MAX_VALUE;//将新的空间设置为int的最大值
            }
            value = Arrays.copyOf(value, newCapacity);//拷贝数组
        }
    

    setLength(int newLength)

            public void setLength(int newLength) {
            if (newLength < 0)
                throw new StringIndexOutOfBoundsException(newLength);
            ensureCapacityInternal(newLength);
    
            if (count < newLength) {
                Arrays.fill(value, count, newLength, '\0');
            }
    
            count = newLength;
        }
    

    这也是扩容方法,内部调用ensureCapacityInternal来实现扩容

    之后将数组空的位置填充满

    7.缩容

    trimToSize()

            public void trimToSize() {
            if (count < value.length) {
                value = Arrays.copyOf(value, count);
            }
        }
    

    调用这个方法,若当前的字符的数量小于char数组空间大小 则缩容,发起拷贝数组。释放多余的空间

    8.得到字符

    charAt(int index)

    直接返回下标对应的字符,若超出范围则抛出异常

    9.得到子字符串/子序列

    substring(int start)/substring(int start, int end)/subSequence(int start,int end)

            public String substring(int start) {
            return substring(start, count);
        }
            public CharSequence subSequence(int start, int end) {
            return substring(start, end);
        }
            public String substring(int start, int end) {
            if (start < 0)
                throw new StringIndexOutOfBoundsException(start);
            if (end > count)
                throw new StringIndexOutOfBoundsException(end);
            if (start > end)
                throw new StringIndexOutOfBoundsException(end - start);
            return new String(value, start, end - start);
        }
    

    调用String的构造方法来实现截取子串。

    10.修改字符

    setCharAt(int index,char ch)

            public void setCharAt(int index, char ch) {
            if ((index < 0) || (index >= count))
                throw new StringIndexOutOfBoundsException(index);
            value[index] = ch;
        }
    

    replace(int start, int end, String str)

    用字符串str替换 start到end部分的字符 前闭后开[start,end)

    public AbstractStringBuilder replace(int start, int end, String str) {
            if (start < 0)
                throw new StringIndexOutOfBoundsException(start);
            if (start > count)
                throw new StringIndexOutOfBoundsException("start > length()");
            if (start > end)
                throw new StringIndexOutOfBoundsException("start > end");
    
            if (end > count)//若传入的参数最后的位置大于字符总数,修改end
                end = count;
            int len = str.length();
                //todo 为什么要扩容
            int newCount = count + len - (end - start);
            ensureCapacityInternal(newCount);
                    // 拷贝数组 替换
            System.arraycopy(value, end, value, start + len, count - end);
            str.getChars(value, start);
            count = newCount;
            return this;
        }
    

    11.追加字符串

    该类提供的append()有很多

            public AbstractStringBuilder append(Object obj) {
            return append(String.valueOf(obj));
        }
            public AbstractStringBuilder append(String str) {
            if (str == null)//若字符串为空
                return appendNull();//而是添加"null"进字符串数组中
            int len = str.length();
            ensureCapacityInternal(count + len);
            str.getChars(0, len, value, count);
            count += len;
            return this;
        }
            private AbstractStringBuilder appendNull() {
            int c = count;
            ensureCapacityInternal(c + 4);
            final char[] value = this.value;
            value[c++] = 'n';
            value[c++] = 'u';
            value[c++] = 'l';
            value[c++] = 'l';
            count = c;
            return this;
        }
    
        // Documentation in subclasses because of synchro difference
        public AbstractStringBuilder append(StringBuffer sb) {
            if (sb == null)
                return appendNull();
            int len = sb.length();
            ensureCapacityInternal(count + len);
            sb.getChars(0, len, value, count);
            count += len;
            return this;
        }
            /**
         * @since 1.8
         */
        AbstractStringBuilder append(AbstractStringBuilder asb) {
            if (asb == null)
                return appendNull();
            int len = asb.length();
            ensureCapacityInternal(count + len);
            asb.getChars(0, len, value, count);
            count += len;
            return this;
        }
    
        // Documentation in subclasses because of synchro difference
        @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());
        }
            public AbstractStringBuilder append(char[] str) {
            int len = str.length;
            ensureCapacityInternal(count + len);
            System.arraycopy(str, 0, value, count, len);
            count += len;
            return this;
        }
            public AbstractStringBuilder append(boolean b) {//添加的布尔将其转换成对应的字符的表达
            if (b) {
                ensureCapacityInternal(count + 4);
                value[count++] = 't';
                value[count++] = 'r';
                value[count++] = 'u';
                value[count++] = 'e';
            } else {
                ensureCapacityInternal(count + 5);
                value[count++] = 'f';
                value[count++] = 'a';
                value[count++] = 'l';
                value[count++] = 's';
                value[count++] = 'e';
            }
            return this;
        }
        public AbstractStringBuilder append(char c) {
            ensureCapacityInternal(count + 1);
            value[count++] = c;
            return this;
        }
            // int long float double. 不一一列举了
            public AbstractStringBuilder append(int i) {
            if (i == Integer.MIN_VALUE) {
                append("-2147483648");
                return this;
            }
            int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
                                         : Integer.stringSize(i);
            int spaceNeeded = count + appendedLength;
            ensureCapacityInternal(spaceNeeded);
            Integer.getChars(i, spaceNeeded, value);
            count = spaceNeeded;
            return this;
        }
    

    除了参数类型不同 其他都差不多,执行扩容并添加操作。直接链接到原value[]的实际count的后面

    同时注意返回的都是AbstractStringBuilder,意味着append方法可以连续无限调用,即AbstractStringBuilder对象.append(参数1).append(参数2).append(参数三)…………;

    12.插入字符串

    除了可以在末尾追加字符串 还可以在任意的位置进行插入字符串.

    在value[]的下标为index位置插入数组str的一部分,该部分的范围为:[offset,offset+len);

    public AbstractStringBuilder insert(int index, char[] str, int offset,
                                            int len)
        {
            if ((index < 0) || (index > length()))
                throw new StringIndexOutOfBoundsException(index);
            if ((offset < 0) || (len < 0) || (offset > str.length - len))
                throw new StringIndexOutOfBoundsException(
                    "offset " + offset + ", len " + len + ", str.length "
                    + str.length);
            ensureCapacityInternal(count + len);
            System.arraycopy(value, index, value, index + len, count - index);
            System.arraycopy(str, offset, value, index, len);
            count += len;
            return this;
        }
    

    原理也都一样,扩容,然后在指定的位置插入,也就是拷贝数组

    还有的插入方法如下:

    insert(int offset,Object obj)
    insert(int offset, String str)
    insert(int offset, char str[])
    insert(int dstOffset, CharSequence s)/insert(int dstOffset, CharSequence s,int start, int end):插入字符序列
    插入基本类型insert(int offset, boolean b) /insert(int offset, char c)/insert(int offset, int i)/insert(int offset, float f)/insert(int offset, double d)

    13.删除

    delete(int start, int end):删掉value数组的[start,end)部分,并将end后面的数据移到start位置

            public AbstractStringBuilder delete(int start, int end) {
            if (start < 0)
                throw new StringIndexOutOfBoundsException(start);
            if (end > count)
                end = count;
            if (start > end)
                throw new StringIndexOutOfBoundsException();
            int len = end - start;
            if (len > 0) {
                System.arraycopy(value, start+len, value, start, count-end);
                count -= len;
            }
            return this;
        }
    

    deleteCharAt(int index):删除下标为index的数据,并将后面的数据前移一位

    public AbstractStringBuilder deleteCharAt(int index) {
            if ((index < 0) || (index >= count))
                throw new StringIndexOutOfBoundsException(index);
            System.arraycopy(value, index+1, value, index, count-index-1);
            count--;
            return this;
        }
    

    14.查找

    indexOf(String str):在value[]中找字符串str,若能找到,返回第一个字符串的第一个字符的下标

            public int indexOf(String str) {
            return indexOf(str, 0);
        }
            public int indexOf(String str, int fromIndex) {
            return String.indexOf(value, 0, count, str, fromIndex);
        }
    

    lastIndexOf(String str):从后往前找

            public int lastIndexOf(String str) {
            return lastIndexOf(str, count);
        }
            public int lastIndexOf(String str, int fromIndex) {
            return String.lastIndexOf(value, 0, count, str, fromIndex);
        }
    

    都是借助了String中的查找的方法

    15.翻转字符串

    reverse 将字符串首尾颠倒

            public AbstractStringBuilder reverse() {
            boolean hasSurrogates = false;
            int n = count - 1;
            for (int j = (n-1) >> 1; j >= 0; j--) {
                int k = n - j;
                char cj = value[j];
                char ck = value[k];
                value[j] = ck;
                value[k] = cj;
                if (Character.isSurrogate(cj) ||
                    Character.isSurrogate(ck)) {
                    hasSurrogates = true;
                }
            }
            if (hasSurrogates) {
                reverseAllValidSurrogatePairs();
            }
            return this;
        }
            private void reverseAllValidSurrogatePairs() {
            for (int i = 0; i < count - 1; i++) {
                char c2 = value[i];
                if (Character.isLowSurrogate(c2)) {
                    char c1 = value[i + 1];
                    if (Character.isHighSurrogate(c1)) {
                        value[i++] = c1;
                        value[i] = c2;
                    }
                }
            }
        }
    

    最后

    感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!

    相关文章

      网友评论

        本文标题:这份JDK源码解析,建议反复观看,写的真的跟详细了!

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