字符串比较是编程中的一项基本操作,并且经常在面试中被提问。 这些字符串是字符序列,是不可变的,这意味着它们不会随时间变化或无法更改。
Java 有许多用于比较字符串的方法;本文将教你如何在 Java 中比较字符串的主要操作。
有六种选择
- == 运算符
- String equals
- String equalsIgnoreCase
- String compareTo
- String compareToIgnoreCase
- Objects equals
== 运算符
== 是一个运算符,如果被比较的内容引用相同的内存,则返回 true,如果不是,则返回 false。 如果用 == 比较的两个字符串引用相同的字符串内存,则返回值为 true;如果不是,则返回值为 false。
String string1 = "MYTEXT";
String string2 = "YOURTEXT";
System.out.println("Output: " + (string1 == string2));
Output: false
上面 == 的返回值是 false,因为“MYTEXT”和“YOURTEXT”引用不同的内存。
String string1 = "MYTEXT";
String string6 = "MYTEXT";
System.out.println("Output: " + (string1 == string6));
Output: true
在这种情况下,== 的返回值是 true,因为编译器在内部为两个“MYTEXT”内存创建一个内存位置,并且两个变量都引用相同的内存位置。
String string1 = "MYTEXT";
String string7 = string1;
System.out.println("Output: " + (string1 == string7));
Output: true
如果你猜对了,你就知道 string7 是用与 string1 相同的内存位置初始化的,因此 == 为 true。
String string1 = "MYTEXT";
String string4 = new String("MYTEXT");
System.out.println("Output: " + (string1 == string4));
Output: false
在这种情况下,即使 string4 和 string1 的值相同,编译器也会创建一个新的内存位置。
String string1 = "MYTEXT";
String string5 = new String(string1);
System.out.println("Output: " + (string1 == string4));
Output: false
在这里,string5 是用 string1 初始化的新字符串对象;因此,string1 == string4 不为 true。
String equals
String 类有一个 String 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) { ... }
让我们看几个例子
String string1 = "MYTEXT";
String string2 = "YOURTEXT";
System.out.println("Output: " + string1.equals(string2));
Output: false
如果字符串不相同,则 equals 方法的输出显然是 false。
String string1 = "MYTEXT";
String string3 = "mytext";
System.out.println("Output: " + string1.equals(string3));
Output: false
这些字符串的值相同,但大小写不同;因此,输出为 false。
String string1 = "MYTEXT";
String string4 = new String("MYTEXT");
System.out.println("Output: " + string1.equals(string4));
Output: true
String string1 = "MYTEXT";
String string5 = new String(string1);
System.out.println("Output: " + string1.equals(string5));
Output: true
这两种情况下的示例都为 true,因为两个值相同。 与 == 不同,上面的第二个示例返回 true。
调用 equals 的字符串对象显然应该是一个有效的字符串对象且非空。
String string1 = "MYTEXT";
String string8 = null;
System.out.println("Output: " + string8.equals(string1));
Exception in thread _____ java.lang.NullPointerException
显然这不是一个好的代码。
System.out.println("Output: " + string1.equals(string8));
Output: false
这样是可以的。
String equalsIgnoreCase
equalsIgnoreCase 的行为与 equals 相同,但有一个区别——比较不区分大小写。 文档说
/**
* 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) { ... }
equals(上文)中的第二个示例与 equalsIgnoreCase 中的比较的唯一区别。
String string1 = "MYTEXT";
String string3 = "mytext";
System.out.println("Output: " + string1.equalsIgnoreCase(string3));
Output: true
这返回 true,因为比较是大小写无关的。 equals 下的所有其他示例与 equalsIgnoreCase 的示例保持不变。
String compareTo
compareTo 方法按字典顺序(即,与字母顺序相关)且区分大小写地比较两个字符串,并返回两个字符串中的字典顺序差异。 文档将词典顺序计算描述为
/**
* Compares two strings lexicographically.
* The comparison is based on the Unicode value of each character in
* the strings. The character sequence represented by this
* {@code String} object is compared lexicographically to the
* character sequence represented by the argument string. The result is
* a negative integer if this {@code String} object
* lexicographically precedes the argument string. The result is a
* positive integer if this {@code String} object lexicographically
* follows the argument string. The result is zero if the strings
* are equal; {@code compareTo} returns {@code 0} exactly when
* the {@link #equals(Object)} method would return {@code true}.
* <p>
* This is the definition of lexicographic ordering. If two strings are
* different, then either they have different characters at some index
* that is a valid index for both strings, or their lengths are different,
* or both. If they have different characters at one or more index
* positions, let <i>k</i> be the smallest such index; then the string
* whose character at position <i>k</i> has the smaller value, as
* determined by using the < operator, lexicographically precedes the
* other string. In this case, {@code compareTo} returns the
* difference of the two character values at position {@code k} in
* the two string -- that is, the value:
* <blockquote><pre>
* this.charAt(k)-anotherString.charAt(k)
* </pre></blockquote>
* If there is no index position at which they differ, then the shorter
* string lexicographically precedes the longer string. In this case,
* {@code compareTo} returns the difference of the lengths of the
* strings -- that is, the value:
* <blockquote><pre>
* this.length()-anotherString.length()
* </pre></blockquote>
*
* @param anotherString the {@code String} to be compared.
* @return the value {@code 0} if the argument string is equal to
* this string; a value less than {@code 0} if this string
* is lexicographically less than the string argument; and a
* value greater than {@code 0} if this string is
* lexicographically greater than the string argument.
*/
public int compareTo(String anotherString) { ... }
让我们看一些例子。
String string1 = "A";
String string2 = "B";
System.out.println("Output: " + string1.compareTo(string2));
Output: -1
System.out.println("Output: " + string2.compareTo(string1));
Output: 1
String string1 = "A";
String string3 = "a";
System.out.println("Output: " + string1.compareTo(string3));
Output: -32
System.out.println("Output: " + string3.compareTo(string1));
Output: 32
String string1 = "A";
String string6 = "A";
System.out.println("Output: " + string1.compareTo(string6));
Output: 0
String string1 = "A";
String string8 = null;
System.out.println("Output: " + string8.compareTo(string1));
Exception in thread ______ java.lang.NullPointerException
at java.lang.String.compareTo(String.java:1155)
String string1 = "A";
String string10 = "";
System.out.println("Output: " + string1.compareTo(string10));
Output: 1
String compareToIgnoreCase
compareToIgnoreCase 的行为与 compareTo 相同,但有一个区别:字符串的比较不考虑大小写。
String string1 = "A";
String string3 = "a";
System.out.println("Output: " + string1.compareToIgnoreCase(string3));
Output: 0
Objects equals
Objects equals 方法调用重写的 String equals 方法;它的行为与上面的 String equals 示例相同。
String string1 = "MYTEXT";
String string2 = "YOURTEXT";
System.out.println("Output: " + Objects(string1, string2));
Output: false
String string1 = "MYTEXT";
String string3 = "mytext";
System.out.println("Output: " + Objects(string1, string3));
Output: false
String string1 = "MYTEXT";
String string6 = "MYTEXT";
System.out.println("Output: " + Objects(string1, string6));
Output: true
String string1 = "MYTEXT";
String string8 = null;
System.out.println("Output: " + Objects.equals(string1, string8));
Output: false
System.out.println("Output: " + Objects.equals(string8, string1));
Output: false
String string8 = null;
String string9 = null;
System.out.println("Output: " + Objects.equals(string8, string9));
Output: true
这里的优点是 Objects equals 方法检查空值(与 String equals 不同)。 Object equals 的实现是
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
应该使用哪种方法?
有很多方法可以比较两个字符串。 应该使用哪一个? 作为一种常见的做法,对于区分大小写的字符串使用 String equals,对于不区分大小写的比较使用 String equalsIgnoreCase。 但是,需要注意一个问题:如果一个或两个字符串为空,请注意 NPE (NullPointerException)。
评论已关闭。