1. 程式人生 > >Java中字串比較方法equals()和equalsIgnoreCase()的區別

Java中字串比較方法equals()和equalsIgnoreCase()的區別

1. equals()

equals( )是比較兩個字串是否相等,它的一般表示式如下:

/**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
     *
     * @param  anObject
     *         The object to compare this {@code String} against
     *
     * @return  {@code true} if the given object represents a {@code String}
     *          equivalent to this string, {@code false} otherwise
     *
     * @see  #compareTo(String)
     * @see  #equalsIgnoreCase(String)
     */
    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;
    }

看這段程式碼前,我們有必要先了解一下字串本身。字串是一個比較特殊的物件。它之所以特俗是因為Java會在記憶體中為String型別的物件開闢一個空間,我們叫它串池。字串物件建立之後會放到串池中。

串池有一個特點就是,對於相同物件,串池中只儲存一份。那麼問題是,串池會把什麼樣子的字串物件看作是相同的物件呢?

String a = "abc";和String  b = "abc";對於這樣的型別宣告方式(不是new出來的),串池會把他們看作是相同的字串物件。所以呢,在串池中只會儲存一份。變數 a and b只是兩個引用罷了。

對於String只要用new關鍵字new出來的,都是一個獨立的物件。

下面看看上面這段程式碼,String是對equals方法進行了重寫。第一步用了兩個字串的“==”判斷,“==”判斷的是兩個字串的記憶體地址,只要不是串池中唯一的自己比自己都會返回 false。所以它是對兩個引用做的的比較,判斷他們是否指向統一記憶體地址。

接著下面

while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }

下面是對字串的內容進行比較,也就是對兩個String物件的比較。

注意:

1.對於"=="如果基於基本資料型別的變數,則是直接比較其儲存的“值”是否相等。如果作用於引用型別的變數,則比較的是所指向的記憶體地址是否相同。

2. 對於equals方法,它不能作用於基本型別的變數,如果沒有對equals進行重寫則比較的是引用變數指向的記憶體地址。

2. equalsIgnoreCase()

執行忽略大小寫的比較,當比較兩個字串時,它會認為A-Z和a-z是一樣的。

 /**
     * Compares this {@code String} to another {@code String}, ignoring case
     * considerations.  Two strings are considered equal ignoring case if they
     * are of the same length and corresponding characters in the two strings
     * are equal ignoring case.
     *
     * <p> Two characters {@code c1} and {@code c2} are considered the same
     * ignoring case if at least one of the following is true:
     * <ul>
     *   <li> The two characters are the same (as compared by the
     *        {@code ==} operator)
     *   <li> Applying the method {@link
     *        java.lang.Character#toUpperCase(char)} to each character
     *        produces the same result
     *   <li> Applying the method {@link
     *        java.lang.Character#toLowerCase(char)} to each character
     *        produces the same result
     * </ul>
     *
     * @param  anotherString
     *         The {@code String} to compare this {@code String} against
     *
     * @return  {@code true} if the argument is not {@code null} and it
     *          represents an equivalent {@code String} ignoring case; {@code
     *          false} otherwise
     *
     * @see  #equals(Object)
     */
    public boolean equalsIgnoreCase(String anotherString) {
        return (this == anotherString) ? true
                : (anotherString != null)
                && (anotherString.value.length == value.length)
                && regionMatches(true, 0, anotherString, 0, value.length);
    }



 /**
     * Tests if two string regions are equal.
     * <p>
     * A substring of this {@code String} object is compared to a substring
     * of the argument {@code other}. The result is {@code true} if these
     * substrings represent character sequences that are the same, ignoring
     * case if and only if {@code ignoreCase} is true. The substring of
     * this {@code String} object to be compared begins at index
     * {@code toffset} and has length {@code len}. The substring of
     * {@code other} to be compared begins at index {@code ooffset} and
     * has length {@code len}. The result is {@code false} if and only if
     * at least one of the following is true:
     * <ul><li>{@code toffset} is negative.
     * <li>{@code ooffset} is negative.
     * <li>{@code toffset+len} is greater than the length of this
     * {@code String} object.
     * <li>{@code ooffset+len} is greater than the length of the other
     * argument.
     * <li>{@code ignoreCase} is {@code false} and there is some nonnegative
     * integer <i>k</i> less than {@code len} such that:
     * <blockquote><pre>
     * this.charAt(toffset+k) != other.charAt(ooffset+k)
     * </pre></blockquote>
     * <li>{@code ignoreCase} is {@code true} and there is some nonnegative
     * integer <i>k</i> less than {@code len} such that:
     * <blockquote><pre>
     * Character.toLowerCase(this.charAt(toffset+k)) !=
     Character.toLowerCase(other.charAt(ooffset+k))
     * </pre></blockquote>
     * and:
     * <blockquote><pre>
     * Character.toUpperCase(this.charAt(toffset+k)) !=
     *         Character.toUpperCase(other.charAt(ooffset+k))
     * </pre></blockquote>
     * </ul>
     *
     * @param   ignoreCase   if {@code true}, ignore case when comparing
     *                       characters.
     * @param   toffset      the starting offset of the subregion in this
     *                       string.
     * @param   other        the string argument.
     * @param   ooffset      the starting offset of the subregion in the string
     *                       argument.
     * @param   len          the number of characters to compare.
     * @return  {@code true} if the specified subregion of this string
     *          matches the specified subregion of the string argument;
     *          {@code false} otherwise. Whether the matching is exact
     *          or case insensitive depends on the {@code ignoreCase}
     *          argument.
     */
    public boolean regionMatches(boolean ignoreCase, int toffset,
            String other, int ooffset, int len) {
        char ta[] = value;
        int to = toffset;
        char pa[] = other.value;
        int po = ooffset;
        // Note: toffset, ooffset, or len might be near -1>>>1.
        if ((ooffset < 0) || (toffset < 0)
                || (toffset > (long)value.length - len)
                || (ooffset > (long)other.value.length - len)) {
            return false;
        }
        while (len-- > 0) {
            char c1 = ta[to++];
            char c2 = pa[po++];
            if (c1 == c2) {
                continue;
            }
            if (ignoreCase) {
                // If characters don't match but case may be ignored,
                // try converting both characters to uppercase.
                // If the results match, then the comparison scan should
                // continue.
                char u1 = Character.toUpperCase(c1);
                char u2 = Character.toUpperCase(c2);
                if (u1 == u2) {
                    continue;
                }
                // Unfortunately, conversion to uppercase does not work properly
                // for the Georgian alphabet, which has strange rules about case
                // conversion.  So we need to make one last check before
                // exiting.
                if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                    continue;
                }
            }
            return false;
        }
        return true;
    }

regionMatches 的基本定義是:regionMatches(int firstStart, String other, int otherStart, int len)

表示從當前字串的firstStart位置開始,取一個長度為len的子串;然後從另一個字串other的otherStart位置開始也取一個長度為len的子串,然後比較這兩個子串是否相同,如果這兩個子串相同則返回true,否則返回false。

我們看到的上面這個方法是對regionMatches方法的過載。比較方式基本相同,就是多了一個Boolean型別的引數,用來確定比較的時候是否忽略大小寫。當ignoreCase為true表示忽略大小寫。