程序员

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

2020-07-21  本文已影响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相关技术文章或行业资讯,欢迎大家关注和转发文章!

上一篇下一篇

猜你喜欢

热点阅读