AbstractStringBuilder

    xiaoxiao2022-07-07  191

    看了下StringBuilder得源码,发现是继承了AbstractStringBuilder,StringBuilder里面得功能比如append,length()等函数得实现是通过调用了AbstractStringBuilder类里面得函数来实现了,所以就看下AbstractStringBuilder是如何实现这些功能得。

    AbstractStringBuilder 里面是通过char [] 来保存数据,在构造函数中指定缓冲区得大小

      

      /**      * Creates an AbstractStringBuilder of the specified capacity.      */     AbstractStringBuilder(int capacity) {         value = new char[capacity];     }

    既然是数组,那么大capacity 大小不够得时候,需要扩容,调用ensureCapacity来实现得。

      

      /**      * Ensures that the capacity is at least equal to the specified minimum.      * If the current capacity is less than the argument, then a new internal      * array is allocated with greater capacity. The new capacity is the      * larger of:      * <ul>      * <li>The {@code minimumCapacity} argument.      * <li>Twice the old capacity, plus {@code 2}.      * </ul>      * If the {@code minimumCapacity} argument is nonpositive, this      * method takes no action and simply returns.      * Note that subsequent operations on this object can reduce the      * actual capacity below that requested here.      *      * @param   minimumCapacity   the minimum desired capacity.      */     public void ensureCapacity(int minimumCapacity) {         if (minimumCapacity > 0)             ensureCapacityInternal(minimumCapacity);     }

    调用的ensureCapacityInternal

       

    /**      * For positive values of {@code minimumCapacity}, this method      * behaves like {@code ensureCapacity}, however it is never      * synchronized.      * If {@code minimumCapacity} is non positive due to numeric      * overflow, this method throws {@code OutOfMemoryError}.      */     private void ensureCapacityInternal(int minimumCapacity) {         // overflow-conscious code         if (minimumCapacity - value.length > 0) {             value = Arrays.copyOf(value,                     newCapacity(minimumCapacity));         }     }

    如何要扩大得容量比起当前得数据得大小要大,则拷贝数据。

     

      private int newCapacity(int minCapacity) {         // overflow-conscious code         int newCapacity = (value.length << 1) + 2;         if (newCapacity - minCapacity < 0) {             newCapacity = minCapacity;         }         return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)             ? hugeCapacity(minCapacity)             : newCapacity;     }

    新得大小是当前得大小得两倍 + 2,如果比要扩容得大小要小,就设置扩容得大小为传进来得大小,让newCapacity 跟Integer.MAX_VALUE对比,如果比其大,则报OutOfMemoryError 异常。

    append()函数可以穿很多种数据类型,所以有各个类型得重载,所以这里看下传String得实现。

        

    /**      * Appends the specified string to this character sequence.      * <p>      * The characters of the {@code String} argument are appended, in      * order, increasing the length of this sequence by the length of the      * argument. If {@code str} is {@code null}, then the four      * characters {@code "null"} are appended.      * <p>      * Let <i>n</i> be the length of this character sequence just prior to      * execution of the {@code append} method. Then the character at      * index <i>k</i> in the new character sequence is equal to the character      * at index <i>k</i> in the old character sequence, if <i>k</i> is less      * than <i>n</i>; otherwise, it is equal to the character at index      * <i>k-n</i> in the argument {@code str}.      *      * @param   str   a string.      * @return  a reference to this object.      */     public AbstractStringBuilder append(String str) {         if (str == null)             return appendNull();         int len = str.length();         ensureCapacityInternal(count + len);         str.getChars(0, len, value, count);         count += len;         return this;     }

    首先先确保append 上str后得容量足够,然后调用getChars ,接着更新当前得大小。看下getChars 得实现。

       

    /**      * Characters are copied from this sequence into the      * destination character array {@code dst}. The first character to      * be copied is at index {@code srcBegin}; the last character to      * be copied is at index {@code srcEnd-1}. The total number of      * characters to be copied is {@code srcEnd-srcBegin}. The      * characters are copied into the subarray of {@code dst} starting      * at index {@code dstBegin} and ending at index:      * <pre>{@code      * dstbegin + (srcEnd-srcBegin) - 1      * }</pre>      *      * @param      srcBegin   start copying at this offset.      * @param      srcEnd     stop copying at this offset.      * @param      dst        the array to copy the data into.      * @param      dstBegin   offset into {@code dst}.      * @throws     IndexOutOfBoundsException  if any of the following is true:      *             <ul>      *             <li>{@code srcBegin} is negative      *             <li>{@code dstBegin} is negative      *             <li>the {@code srcBegin} argument is greater than      *             the {@code srcEnd} argument.      *             <li>{@code srcEnd} is greater than      *             {@code this.length()}.      *             <li>{@code dstBegin+srcEnd-srcBegin} is greater than      *             {@code dst.length}      *             </ul>      */     public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)     {         if (srcBegin < 0)             throw new StringIndexOutOfBoundsException(srcBegin);         if ((srcEnd < 0) || (srcEnd > count))             throw new StringIndexOutOfBoundsException(srcEnd);         if (srcBegin > srcEnd)             throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");         System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);     }

    调用系统得arraycopy 数组拷贝函数来实现数据得拷贝。

      

      /**      * Appends the string representation of the {@code boolean}      * argument to the sequence.      * <p>      * The overall effect is exactly as if the argument were converted      * to a string by the method {@link String#valueOf(boolean)},      * and the characters of that string were then      * {@link #append(String) appended} to this character sequence.      *      * @param   b   a {@code boolean}.      * @return  a reference to this object.      */     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;     }

    append bool类型得数据,还是比较容易看懂得。

    看下replace 函数得实现

     

     /**      * Replaces the characters in a substring of this sequence      * with characters in the specified {@code String}. The substring      * begins at the specified {@code start} and extends to the character      * at index {@code end - 1} or to the end of the      * sequence if no such character exists. First the      * characters in the substring are removed and then the specified      * {@code String} is inserted at {@code start}. (This      * sequence will be lengthened to accommodate the      * specified String if necessary.)      *      * @param      start    The beginning index, inclusive.      * @param      end      The ending index, exclusive.      * @param      str   String that will replace previous contents.      * @return     This object.      * @throws     StringIndexOutOfBoundsException  if {@code start}      *             is negative, greater than {@code length()}, or      *             greater than {@code 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 = count;         int len = str.length();         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;     }

    里面得实现得步骤跟append 函数得实现流程差不多,先判断 start ,end 是否满足,然后确保容量满足,接着调用System.arraycopy来实现数据拷贝。

     

    AbstractStringBuilder是非线程安全得,里面得函数得实现没有用到synchronized 线程安全,但是AbstractStringBuilder 得运行速度比起线程安全要快。

     

     

    最新回复(0)