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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章