String的部分源码分析(compareTo、valueOf、indexOf、lastIndexOf)(二)

1.String的compareTo方法源码:

java中的compareto方法,返回参与比较的前后两个字符串的asc码的差值,看下面一组代码

   public int compareTo(String anotherString) {

//获取被比较字符串的长度
        int len1 = value.length;

/获取比较字符串的长度
        int len2 = anotherString.value.length;

//取出两个长度的最小值
        int lim = Math.min(len1, len2);

//将字符串转为为字符数组
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;

//从第一个位置开始到长度的最小长度比较两个数组中的字符串ASC码大小
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {

//如果不相等就返回从左到右字符串的相同位置不同字符的asc码差值。
                return c1 - c2;
            }
            k++;
        }

//如果两个字符串最小长度前面的字符都同等,返回两个字符串的差值
        return len1 - len2;
    }


案例:



2.String的valueOf方法源码:

JDK提供了其他基本类型转换为String类型的方法valueOf的很多重载方法,如下图:


其底层实现方式都是对类型进行了重新的封装

    public static String valueOf(char c) {
        char data[] = {c};
        return new String(data, true);
    }

//通过构造方法将其封装为新的String类型

    String(char[] value, boolean share) {
        // assert share : "unshared not supported";
        this.value = value;
    }

3.String的indexOf方法源码:

JDK提供了indexOf的很多重载方法,如下图:


其实indexOf的重载方法的实现都是相互调用的;例如:

(1)对于判断以X字符的ASC码为开始位置的indexOf的实现

 public int indexOf(int ch) {

//默认开始位置为0
        return indexOf(ch, 0);
    }

 public int indexOf(int ch, int fromIndex) {
        final int max = value.length;

//如果开始位置小于0,则默认为0
        if (fromIndex < 0) {
            fromIndex = 0;

//如果开始位置大于源字符串长度,返回-1
        } else if (fromIndex >= max) {
            // Note: fromIndex might be near -1>>>1.
            return -1;
        }

//增补代码点的最小值Character.MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid code point))
            final char[] value = this.value;

//循环比较是否有字符的ASC码和它一致,如果一直就返回
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {

//否则通过另一条线进行判断
            return indexOfSupplementary(ch, fromIndex);
        }
    }

    private int indexOfSupplementary(int ch, int fromIndex) {
        if (Character.isValidCodePoint(ch)) {
            final char[] value = this.value;
            final char hi = Character.highSurrogate(ch);
            final char lo = Character.lowSurrogate(ch);
            final int max = value.length - 1;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == hi && value[i + 1] == lo) {
                    return i;
                }
            }
        }
        return -1;
    }

首先char hi是高代理 char lo是低代理 参数ch是代码点
高代理的算法是这样的:
public static char highSurrogate(int codePoint) {
return (char) ((codePoint >>> 10)
+ (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
}
高代理是将参数codePoint右移10位,加上D800这个字符减去65536右移16位之后所得数的差,然后强转为char类型
低代理的算法是
public static char lowSurrogate(int codePoint) {
return (char) ((codePoint & 0x3ff) + MIN_LOW_SURROGATE);
}
低代理是将参数与1023进行按位运算,就是将两个数转换成二进制,每一位进行比较,如果两个数的对应数位上有一个是0,那么结果对应数位就是0,最后得到的结果转换成十进制,然后再加上DC00这个字符,得到的结果进行强转为char


    public static boolean isValidCodePoint(int codePoint) {
        // Optimized form of:
        //     codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT
        int plane = codePoint >>> 16;
        return plane < ((MAX_CODE_POINT + 1) >>> 16);
    }

(2)对于判断以X字符为开始位置的indexOf的实现

  public int indexOf(String str) {

//默认从零位置开始
        return indexOf(str, 0);
    }

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

最终调用的是static静态方法:

//参数分别为:源字符数组、源偏移量、源字符串长度、目标字符数组、目标偏移量、目标字符数组长度、开始位置

static int indexOf(char[] source, int sourceOffset, int sourceCount,char[] target, int targetOffset, int targetCount,int fromIndex) {

//判断开始位置是否大于等于源字符串长度
        if (fromIndex >= sourceCount) {

//如果目标字符数组长度为0,即“”,返回的是源字符串长度;否则,返回为-1
            return (targetCount == 0 ? sourceCount : -1);

// System.out.println("abcd".indexOf("",5)); //4
        }

//如果开始位置小于0,进行初始化为0
        if (fromIndex < 0) {
            fromIndex = 0;
        }

//如果目标字符串长度为0时,直接返回开始位置的值,例如“”
        if (targetCount == 0) {
            return fromIndex;
        }

//获取目标字符串的首个字符
        char first = target[targetOffset];

//计算需要比较到值
        int max = sourceOffset + (sourceCount - targetCount);

//从开始比较位置开始进行一个一个比较;(目标字符串的第一个位置和源字符串进行一个一个比较)
        for (int i = sourceOffset + fromIndex; i <= max; i++) {
            /* Look for first character. */

//首先来lock第一个字符相同的位置
            if (source[i] != first) {
                while (++i <= max && source[i] != first);
            }


            /* Found first character, now look at the rest of v2 */
            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++);
//如果最后字符各个位置都相同,时当j==end(最后一个);这样就保证了目标字符串被包含
                if (j == end) {
                    /* Found whole string. */

//返回第一次重叠的位置;锁定第一字符相同的位置减去源字符的偏移量,一遍偏移量为0
                    return i - sourceOffset;
                }
            }
        }
        return -1;
    }

4.String中lastIndexOf的方法源码:

由于lastIndexOf和indexOf的返回目的完全相反,这样其实现逻辑也大致相同在这我就只把源码进行粘贴供大家了解:


(1)

   public int lastIndexOf(int ch) {
        return lastIndexOf(ch, value.length - 1);
    }

public int lastIndexOf(int ch, int fromIndex) {
        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid 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 {
            return lastIndexOfSupplementary(ch, fromIndex);
        }
    }

 private int lastIndexOfSupplementary(int ch, int fromIndex) {
        if (Character.isValidCodePoint(ch)) {
            final char[] value = this.value;
            char hi = Character.highSurrogate(ch);
            char lo = Character.lowSurrogate(ch);
            int i = Math.min(fromIndex, value.length - 2);
            for (; i >= 0; i--) {
                if (value[i] == hi && value[i + 1] == lo) {
                    return i;
                }
            }
        }
        return -1;
    }

(2)

 public int lastIndexOf(String str) {
        return lastIndexOf(str, value.length);
    }

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

 static int lastIndexOf(char[] source, int sourceOffset, int sourceCount,
            char[] target, int targetOffset, int targetCount,
            int fromIndex) {
        /*
         * Check arguments; return immediately where possible. For
         * consistency, don't check for null str.
         */
        int rightIndex = sourceCount - targetCount;
        if (fromIndex < 0) {
            return -1;
        }
        if (fromIndex > rightIndex) {
            fromIndex = rightIndex;
        }
        /* Empty string always matches. */
        if (targetCount == 0) {
            return fromIndex;
        }


        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;
        }
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值