Java源码阅读之String(4)

来源:互联网 发布:淘宝收费标准 编辑:程序博客网 时间:2024/05/18 02:59

Java源码阅读之String(4)

这一篇博客主要阅读String类的查找和替换相关的方法。

    /*    *查询当前对象的哈希码,如果当前对象没有计算过哈希码    *则计算当前对象的哈希码并赋值给当前对象的hash对象    *计算方法为:    *value[0]*31^(n-1)+value[1]*31^(n-2)+...+value[n-2]*31+value[n-1]    *计算出结果后再赋值给对象的hash变量    *String对象的equals方法比较的就是hash值,也就是保证了两者的内容一样    */    public int hashCode() {        int h = hash;        if (h == 0 && value.length > 0) {            char val[] = value;            for (int i = 0; i < value.length; i++) {                h = 31 * h + val[i];            }            hash = h;        }        return h;    }    //查询所给的unicode值ch,在当前对象中第一次出现的位置    public int indexOf(int ch) {        return indexOf(ch, 0);    }    //查询所给的unicode值ch,在当前对象中从偏移量fromIndex开始,第一次出现的位置    public int indexOf(int ch, int fromIndex) {        final int max = value.length;        //检查偏移量是否合法        if (fromIndex < 0) {            fromIndex = 0;        } else if (fromIndex >= max) {            return -1;        }        //判断所给unicode代码点是否是高位码点,即是否大于0x00FFFF        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {            final char[] value = this.value;            for (int i = fromIndex; i < max; i++) {                if (value[i] == ch) {                    return i;                }            }            return -1;        } else {            //如果是高位码点,调取indexOfSupplementary方法进行查询            return indexOfSupplementary(ch, fromIndex);        }    }    //查询高位Unicode代码点在当前对象,从偏移量fromIndex开始第一次出现的位置    private int indexOfSupplementary(int ch, int fromIndex) {        //判断ch是否为合法的Unicode代码点        if (Character.isValidCodePoint(ch)) {            final char[] value = this.value;            //将ch的高位码点转换为char            final char hi = Character.highSurrogate(ch);            //将ch的低位码点转换为char            final char lo = Character.lowSurrogate(ch);            final int max = value.length - 1;            for (int i = fromIndex; i < max; i++) {                //查询相邻的两个char分别等于高位码点的char和低位码点的char                if (value[i] == hi && value[i + 1] == lo) {                    return i;                }            }        }        return -1;    }    //查询所给的unicode值ch,在当前对象中最后一次出现的位置    public int lastIndexOf(int ch) {        return lastIndexOf(ch, value.length - 1);    }    //查询所给的unicode值ch,在当前对象中从偏移量fromIndex开始,最后一次出现的位置    public int lastIndexOf(int ch, int fromIndex) {        //判断所给unicode代码点是否是高位码点,即是否大于0x00FFFF        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {                        final char[] value = this.value;            int i = Math.min(fromIndex, value.length - 1);            for (; i >= 0; i--) {                if (value[i] == ch) {                    return i;                }            }            return -1;        } else {            //如果是高位码点,调取lastIndexOfSupplementary方法进行查询            return lastIndexOfSupplementary(ch, fromIndex);        }    }    //查询高位Unicode代码点在当前对象,从偏移量fromIndex开始最后一次出现的位置    private int lastIndexOfSupplementary(int ch, int fromIndex) {        if (Character.isValidCodePoint(ch)) {            final char[] value = this.value;            //将ch的高位码点转换为char            char hi = Character.highSurrogate(ch);            //将ch的低位码点转换为char            char lo = Character.lowSurrogate(ch);            int i = Math.min(fromIndex, value.length - 2);            //查询相邻的两个char分别等于高位码点的char和低位码点的char            for (; i >= 0; i--) {                if (value[i] == hi && value[i + 1] == lo) {                    return i;                }            }        }        return -1;    }    //根据所给的String对象str作为子串出现在当前对象的第一次位置    public int indexOf(String str) {        return indexOf(str, 0);    }    //根据所给的String对象str作为子串,从偏移量fromIndex开始出现在当前对象的第一次位置    public int indexOf(String str, int fromIndex) {        return indexOf(value, 0, value.length,                str.value, 0, str.value.length, fromIndex);    }    //在所给的source数组中,从偏移量sourceOffset+fromIndex开始查找target作为子串第一次出现的位置    static int indexOf(char[] source, int sourceOffset, int sourceCount,            String target, int fromIndex) {        return indexOf(source, sourceOffset, sourceCount,                       target.value, 0, target.value.length,                       fromIndex);    }    /*在所给的source数组中,从偏移量sourceOffset+fromIndex开始查找    *target中从偏移量targetOffset开始作为子串第一次出现的位置    *sourceOffset原数组开始偏移量,sourceCount原数组偏移量后剩余长度    *targetOffset目标数组开始偏移量,targetCount目标数组偏移量后剩余长度    *fromIndex开始查找的位置    *之所以不使用KMP算法是因为,JDK的编写者认为调用这个方法的时候,通常字符串不是很长    *使用KMP算法需要付出额外的空间和时间得不偿失,如果需要比较长字符串,那么最好不要调用这个方法    */    static int indexOf(char[] source, int sourceOffset, int sourceCount,            char[] target, int targetOffset, int targetCount,            int fromIndex) {        //判断fromIndex合法性        if (fromIndex >= sourceCount) {            return (targetCount == 0 ? sourceCount : -1);        }        if (fromIndex < 0) {            fromIndex = 0;        }        if (targetCount == 0) {            return fromIndex;        }        //设置第一个需要比较的目标字符        char first = target[targetOffset];        //设置原数组中能比较的最大位置        int max = sourceOffset + (sourceCount - targetCount);        for (int i = sourceOffset + fromIndex; i <= max; i++) {            //查找原数组中出现第一个目标字符的位置            if (source[i] != first) {                while (++i <= max && source[i] != first);            }            //如果找到了第一个目标字符的位置,继续对比            if (i <= max) {                int j = i + 1;                int end = j + targetCount - 1;                for (int k = targetOffset + 1; j < end && source[j]                        == target[k]; j++, k++);                //判断是否找到了                if (j == end) {                    //返回第一次出现的位置                    return i - sourceOffset;                }            }        }        return -1;    }    //根据所给的String对象str作为子串出现在当前对象的最后一次位置    public int lastIndexOf(String str) {        return lastIndexOf(str, value.length);    }    //根据所给的String对象str作为子串,从偏移量fromIndex开始出现在当前对象的最后一次位置    public int lastIndexOf(String str, int fromIndex) {        return lastIndexOf(value, 0, value.length,                str.value, 0, str.value.length, fromIndex);    }    //在所给的source数组中,从偏移量sourceOffset+fromIndex开始查找target作为子串最后一次出现的位置    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,            String target, int fromIndex) {        return lastIndexOf(source, sourceOffset, sourceCount,                       target.value, 0, target.value.length,                       fromIndex);    }    /*在所给的source数组中,从偏移量sourceOffset+fromIndex开始查找    *target中从偏移量targetOffset开始作为子串第一次出现的位置    *sourceOffset原数组开始偏移量,sourceCount原数组偏移量后剩余长度    *targetOffset目标数组开始偏移量,targetCount目标数组偏移量后剩余长度    *fromIndex开始查找的位置    */    static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,            char[] target, int targetOffset, int targetCount,            int fromIndex) {        //检查参数合法性        int rightIndex = sourceCount - targetCount;        if (fromIndex < 0) {            return -1;        }        if (fromIndex > rightIndex) {            fromIndex = rightIndex;        }        if (targetCount == 0) {            return fromIndex;        }        //获取最后一位的char        int strLastIndex = targetOffset + targetCount - 1;        char strLastChar = target[strLastIndex];        //获取比较的终止位置        int min = sourceOffset + targetCount - 1;        int i = min + fromIndex;    startSearchForLastChar://标签,比较完一次之后跳转回这里        while (true) {            //找到第一位相同的位置            while (i >= min && source[i] != strLastChar) {                i--;            }            if (i < min) {                return -1;            }            int j = i - 1;            int start = j - (targetCount - 1);            int k = strLastIndex - 1;            //对比接下来的位置            while (j > start) {                if (source[j--] != target[k--]) {                    i--;                    continue startSearchForLastChar;//返回到标签位置                }            }            return start - sourceOffset + 1;        }    }    //字符串截取,从beginIndex开始,如果beginIndex为0,返回当前对象而不是复制一个新对象    public String substring(int beginIndex) {        if (beginIndex < 0) {            throw new StringIndexOutOfBoundsException(beginIndex);        }        int subLen = value.length - beginIndex;        if (subLen < 0) {            throw new StringIndexOutOfBoundsException(subLen);        }        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);    }    /*字符串截取,从beginIndex开始,到endIndex结束    *如果beginIndex为0且endIndex为当前对象的长度,返回当前对象而不是复制一个新对象    */    public String substring(int beginIndex, int endIndex) {        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);    }    /*字符串截取,从beginIndex开始,到endIndex结束    *如果beginIndex为0且endIndex为当前对象的长度,返回当前对象而不是复制一个新对象    */    public CharSequence subSequence(int beginIndex, int endIndex) {        return this.substring(beginIndex, endIndex);    }    /*字符串连接,将str拼接在当前对象后面,返回一个新的对象。    *不会在原地进行拼接,String不支持在原对象上进行拼接,如果需要    *对原对象进行拼接,请使用StringBuffer(线程安全)或StringBuilder(非线程安全)    */    public String concat(String str) {        int otherLen = str.length();        if (otherLen == 0) {            return this;        }        int len = value.length;        char buf[] = Arrays.copyOf(value, len + otherLen);        str.getChars(buf, len);        return new String(buf, true);    }    /*将当前对象中的第一个oldChar替换为newChar,不是在原对象中进行替换    *而是返回一个新的对象,如果需要在当前对象进行替换    *请使用StringBuffer(线程安全)或StringBuilder(非线程安全)    */    public String replace(char oldChar, char newChar) {        if (oldChar != newChar) {            int len = value.length;            int i = -1;            char[] val = value;             while (++i < len) {                if (val[i] == oldChar) {                    break;                }            }            if (i < len) {                char buf[] = new char[len];                for (int j = 0; j < i; j++) {                    buf[j] = val[j];                }                while (i < len) {                    char c = val[i];                    buf[i] = (c == oldChar) ? newChar : c;                    i++;                }                return new String(buf, true);            }        }        return this;    }    //判断该字符串是否与给定的正则表达式匹配    public boolean matches(String regex) {        return Pattern.matches(regex, this);    }    //判断当前对象是否包含s子字符序列    public boolean contains(CharSequence s) {        return indexOf(s.toString()) > -1;    }    //用给定的字符串替换此当前对象中与给定正则表达式匹配的第一个子字符串。    public String replaceFirst(String regex, String replacement) {        return Pattern.compile(regex).matcher(this).replaceFirst(replacement);    }    //用给定的字符串替换此当前对象中与给定正则表达式匹配的所有子字符串。    public String replaceAll(String regex, String replacement) {        return Pattern.compile(regex).matcher(this).replaceAll(replacement);    }    //用replacement字符序列替换当前对象中所有符合target字符序列的子字符串    public String replace(CharSequence target, CharSequence replacement) {        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));    }

这些就是String类中的查找和替换相关的方法,如果想深入了解,请参阅Java源码。

原创粉丝点击