美文网首页
String中substring源码解析

String中substring源码解析

作者: capo | 来源:发表于2017-08-27 17:21 被阅读55次

简书:capo
转载请注明原创出处,谢谢!

今天我们来分析下JDK>lang>String中的substring方法,下面贴上代码:

/**
      返回一个字符串开始索引是从 0 开始 到 endIndex - 1
      这个字符串的长度是  endIndex - beginIndex
      
     * Returns a string that is a substring of this string. The
     * substring begins at the specified {@code beginIndex} and
     * extends to the character at index {@code endIndex - 1}.
     * Thus the length of the substring is {@code endIndex-beginIndex}.
     * <p>
     * Examples:
     * <blockquote><pre>
     * "hamburger".substring(4, 8) returns "urge"
     * "smiles".substring(1, 5) returns "mile"
     * </pre></blockquote>
     *
                  这个开始索引所在的数据包括
     * @param      beginIndex   the beginning index, inclusive.
                  这个结束索引所在的数据不包括
     * @param      endIndex     the ending index, exclusive.
     * @return     the specified substring.
                   如果这个开始索引是个负数,或者这个结束索引是个非常大的数已经超过了这个字符串的长度,或者这个开始索引已经超过了这个结束索引这3种情况都会抛出 IndexOutOfBoundsException
     * @exception  IndexOutOfBoundsException  if the
     *             {@code beginIndex} is negative, or
     *             {@code endIndex} is larger than the length of
     *             this {@code String} object, or
     *             {@code beginIndex} is larger than
     *             {@code endIndex}.
     */
    public String substring(int beginIndex, int endIndex) {
       //开始索引 < 0 抛异常
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        //结束索引 > 字符数组长度
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        //子字符串长度
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
        //这3个参数 依次为字符数组,  开始索引,    数组长度==
l   }
    

再次调用数组的 Arrays.copyOfRange();方法进行复制

 /**
     * Allocates a new {@code String} that contains characters from a subarray
     * of the character array argument. The {@code offset} argument is the
     * index of the first character of the subarray and the {@code count}
     * argument specifies the length of the subarray. The contents of the
     * subarray are copied; subsequent modification of the character array does
     * not affect the newly created string.
     *
     * @param  value
     *         Array that is the source of characters
     *
     * @param  offset
     *         The initial offset
     *
     * @param  count
     *         The length
     *
     * @throws  IndexOutOfBoundsException
     *          If the {@code offset} and {@code count} arguments index
     *          characters outside the bounds of the {@code value} array
     */
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            //如果偏移量 < 数组长度 返回 ""
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        //如果偏移量(开始下标) > (结束索引)原来字符串长度 - 子字符串长度   
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        // 这3个参数 原始字符串   开始索引   结束索引= 初始索引+子字符串长度
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

再次调用 Arrays.copyOfRange(value,offset,offset+count);方法,==第三个参数是便移量加上数组长度==

   /**
       复制规定了范围新的数组必须是在 0 和原始数组长度之间
     * Copies the specified range of the specified array into a new array.
     * The initial index of the range (<tt>from</tt>) must lie between zero
     * and <tt>original.length</tt>, inclusive.  The value at
     * <tt>original[from]</tt> is placed into the initial element of the copy
     * (unless <tt>from == original.length</tt> or <tt>from == to</tt>).
     * Values from subsequent elements in the original array are placed into
     * subsequent elements in the copy.  The final index of the range
     * (<tt>to</tt>), which must be greater than or equal to <tt>from</tt>,
     * may be greater than <tt>original.length</tt>, in which case
     * <tt>'\\u000'</tt> is placed in all elements of the copy whose index is
     * greater than or equal to <tt>original.length - from</tt>.  The length
     * of the returned array will be <tt>to - from</tt>.
     *
     * @param original the array from which a range is to be copied
     * @param from the initial index of the range to be copied, inclusive
     * @param to the final index of the range to be copied, exclusive.
     *     (This index may lie outside the array.)
     * @return a new array containing the specified range from the original array,
     *     truncated or padded with null characters to obtain the required length
     * @throws ArrayIndexOutOfBoundsException if {@code from < 0}
     *     or {@code from > original.length}
     * @throws IllegalArgumentException if <tt>from > to</tt>
     * @throws NullPointerException if <tt>original</tt> is null
     * @since 1.6
     */
    public static char[] copyOfRange(char[] original, int from, int to) {
       //得到新的数组长度是  = 结束索引 - 开始索引
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        char[] copy = new char[newLength];
        //数组复制的几个参数依次: 原始数组,开始索引,要复制的数组,0 ,原始数组长度 - 新数组长度  求最小值
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }
    

总结一下:

  • substring(beginIndex,endIndex) 它返回的是一个下标从0开始到结束下标-1 的子字符串
  • 这个字符串的长度是 length = endIndex - beingIndex
  • 其内部实现就是首先调用 Arrays.copyOfRange(value,offset,offset+count),注意第三个参数是结束索引 = 开始索引 + 子字符串的长度计算得到的
  • 最后调用底层的 System.arraycopy(original, from, copy, 0,
    Math.min(original.length - from, newLength));
    新的数组规定了必须是一个从0到原始数组长度之间
    Math.min(original.length - from, newLength)取的是根据原始数组-开始索引和新的数组中取一个小的值来当结束索引

相关文章

网友评论

      本文标题:String中substring源码解析

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