jdk8源碼學習之String

String類

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence{}

一旦一個String對象被創建,包含在這個對象中的字符序列是不可改變的,包括該類後續的所有方法都是不能修改該對象的,直至該對象被銷燬,這是我們需要特別注意的(該類的一些方法看似改變了字符串,其實內部都是創建一個新的字符串)

成員變量

/**用來存儲字符串  */
private final char value[];
			
/** 緩存字符串的哈希碼 */
private int hash; // Default to 0
			
/** 實現序列化的標識 */
private static final long serialVersionUID = -6849794470754667710L;
一個 String 字符串實際上是一個 char 數組。

構造方法

String str1 = "abc";
String str2 = new String("abc");
String str3 = new String(new char[]{'a','b','c'});

equals()

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

String 類重寫了equals方法,比較的是組成字符串的每一個字符是否相同,如果都相同則返回true,否則返回false

hashCode()

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

這裏有一個奇怪的數字31,網上查了一下,有以下兩點原因:

第一,31是一個不大不小的質數,是作爲hashCode乘子的優選質數之一。另外一下相近的質數,比如37、41、43等等,也都是不錯的選擇,那麼爲啥偏偏選中了31呢,請看第二個原因。

第二,31可以被JVM優化,31 * i = (i<<5) - i.。

charAt()

    public char charAt(int index) {
        // 如果傳入的索引大於字符串的長度或者小於0,直接拋出索引越界異常
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
        return value[index];
    }

 通過傳入的索引(數組下標),返回指定索引的單個字符。

compareTo()

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;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

按字母順序比較兩個字符串,是基於字符串中每個字符的Unicode值。當兩個字符串某個位置的字符不同時,返回的是這一位置的字符Unicode值之差,當兩個字符串相同時,返回兩個字符串長度之差。

compareToIgnoreCase() 方法在 compareTo 方法的基礎上忽略大小寫,我們知道大寫字母是比小寫字母的Unicode值小32的,底層實現是先都轉換成大寫比較,然後都轉換成小寫進行比較。

concat()

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

首先判斷要拼接的字符串長度是否爲0,如果爲0,則直接返回原字符串。如果部位0,則通過Arrays工具類(後面會詳細介紹這個工具類)的copyOf方法創建一個新的字符數組,長度爲原字符串之和,情面填充原字符串,後面爲空。接着在通過getChars方法將要拼接的字符串放入新字符串後面爲空的位置。

indexOf(int ch, int fromIndex)

public int indexOf(int ch, int fromIndex) {
        final int max = value.length; // max等於字符的長度
        if (fromIndex < 0) { // 指定索引的位置如果小於0,默認從0開始搜索
            fromIndex = 0;
        } else if (fromIndex >= max) {
            // Note: fromIndex might be near -1>>>1.
            // 如果指定索引值大於等於字符的長度(因爲是數組,下標最多隻能是max-1),直接返回-1
            return -1;
        }

        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // 一個char佔用兩個字節,如果ch小於2的16次方(65536),絕大多數字符都在此範圍內
            // handle most cases here (ch is a BMP code point or a
            // negative value (invalid code point))
            final char[] value = this.value;
            for (int i = fromIndex; i < max; i++) { // for循環依次判斷字符串每個字符是否和指定字符相等
                if (value[i] == ch) {
                    return i; // 存在相等的字符,返回第一次出現該字符的索引位置,並終止循環
                }
            }
            return -1; //不存在相等的字符,返回-1
        } else { // 當字符大於65536時,處理的少數情況,該方法會首先判斷是否是有效字符,然後依次進行比較
            return indexOfSupplementary(ch, fromIndex);
        }
    }

indexOf(int ch),參數 ch 其實是字符的 Unicode 值,這裏也可以放單個字符(默認轉成int),作用是返回指定字符第一次出現的此字符串中的索引。其內部是調用 indexOf(int ch, int fromIndex),只不過這裏的 fromIndex =0 ,因爲是從 0 開始搜索;而 indexOf(int ch, int fromIndex) 作用也是返回首次出現的此字符串內的索引,但是從指定索引處開始搜索。

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