如何在 Java 中比较字符串

Java 中有六种比较字符串的方法。
148 位读者喜欢这篇文章。
Javascript code close-up with neon graphic overlay

Jen Wike Huger 拍摄

字符串比较是编程中的一项基本操作,并且经常在面试中被提问。 这些字符串是字符序列,是不可变的,这意味着它们不会随时间变化或无法更改。

Java 有许多用于比较字符串的方法;本文将教你如何在 Java 中比较字符串的主要操作。

有六种选择

  1. == 运算符
  2. String equals
  3. String equalsIgnoreCase
  4. String compareTo
  5. String compareToIgnoreCase
  6. 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 &lt; 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)。

源代码可在 GitLabGitHub 上获得。

接下来要读什么
标签
User profile image.
Girish 在印度的全球 IT 服务组织拥有超过 20 年的技术和软件经验。 Girish 是“I Got”云平台的架构师,该平台旨在利用开源堆栈和微服务、容器化和多租户等现代架构模式来提升金字塔的底部。 Girish 撰写有关开源和技术主题的文章。

评论已关闭。

Creative Commons License本作品采用 Creative Commons Attribution-Share Alike 4.0 International License 授权。
© . All rights reserved.