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表示忽略大小寫。