TranslateProject/sources/tech/20190920 How to compare strings in Java.md
DarkSun 49406995c2 选题: 20190920 How to compare strings in Java
sources/tech/20190920 How to compare strings in Java.md
2019-09-21 00:58:42 +08:00

448 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[#]: collector: (lujun9972)
[#]: translator: ( )
[#]: reviewer: ( )
[#]: publisher: ( )
[#]: url: ( )
[#]: subject: (How to compare strings in Java)
[#]: via: (https://opensource.com/article/19/9/compare-strings-java)
[#]: author: (Girish Managoli https://opensource.com/users/gammayhttps://opensource.com/users/sethhttps://opensource.com/users/clhermansenhttps://opensource.com/users/clhermansen)
How to compare strings in Java
======
There are six ways to compare strings in Java.
![Javascript code close-up with neon graphic overlay][1]
String comparison is a fundamental operation in programming and is often quizzed during interviews. These strings are a sequence of characters that are _immutable_ which means unchanging over time or unable to be changed.
Java has a number of methods for comparing strings; this article will teach you the primary operation of how to compare strings in Java.
There are six options:
1. The == operator
2. String equals
3. String equalsIgnoreCase
4. String compareTo
5. String compareToIgnoreCase
6. Objects equals
### The == operator
**==** is an operator that returns **true** if the contents being compared refer to the same memory or **false** if they don't. If two strings compared with **==** refer to the same string memory, the return value is **true**; if not, it is **false**.
```
[String][2] string1 = "MYTEXT";
[String][2] string2 = "YOURTEXT";
               
[System][3].out.println("Output: " + (string1 == string2));
Output: false
```
The return value of **==** above is **false**, as "MYTEXT" and "YOURTEXT" refer to different memory.
```
[String][2] string1 = "MYTEXT";
[String][2] string6 = "MYTEXT";
               
[System][3].out.println("Output: " + (string1 == string6));
Output: true
```
In this case, the return value of **==** is **true**, as the compiler internally creates one memory location for both "MYTEXT" memories, and both variables refer to the same memory location.
```
[String][2] string1 = "MYTEXT";
[String][2] string7 = string1;
[System][3].out.println("Output: " + (string1 == string7));
Output: true
```
If you guessed right, you know string7 is initialized with the same memory location as string1 and therefore **==** is true.
```
[String][2] string1 = "MYTEXT";
[String][2] string4 = new [String][2]("MYTEXT");
[System][3].out.println("Output: " + (string1 == string4));
Output: false
```
In this case, the compiler creates a new memory location, even though the value is the same for string4 and string1.
```
[String][2] string1 = "MYTEXT";
[String][2] string5 = new [String][2](string1);
[System][3].out.println("Output: " + (string1 == string4));
Output: false
```
Here, string5 is a new string object initialized with string1; hence, **string1 == string4** is not true.
### String equals
The string class has a **String equals** method to compare two strings. String comparison with **equals** is case-sensitive. According to the [docs][4]:
```
    /**
     * 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) { ... }
```
Let's see a few examples:
```
[String][2] string1 = "MYTEXT";
[String][2] string2 = "YOURTEXT";
[System][3].out.println("Output: " + string1.equals(string2));
Output: false
```
If the strings are not the same, the output of the **equals** method is obviously **false**.
```
[String][2] string1 = "MYTEXT";
[String][2] string3 = "mytext";
[System][3].out.println("Output: " + string1.equals(string3));
Output: false
```
These strings are the same in value but differ in case; hence, the output is **false**.
```
[String][2] string1 = "MYTEXT";
[String][2] string4 = new [String][2]("MYTEXT");
[System][3].out.println("Output: " + string1.equals(string4));
Output: true
[/code] [code]
[String][2] string1 = "MYTEXT";
[String][2] string5 = new [String][2](string1);
[System][3].out.println("Output: " + string1.equals(string5));
Output: true
```
The examples in both these cases are **true**, as the two values are the same. Unlike with **==**, the second example above returns **true**.
The string object on which **equals** is called should obviously be a valid string object and non-null.
```
[String][2] string1 = "MYTEXT";
[String][2] string8 = null;
[System][3].out.println("Output: " + string8.equals(string1));
[Exception][5] in thread _____  java.lang.[NullPointerException][6]
```
The above evidently is not a good code.
```
[System][3].out.println("Output: " + string1.equals(string8));
Output: false
```
This is alright.
### String equalsIgnoreCase
The behavior of **equalsIgnoreCase** is identical to **equals** with one difference—the comparison is not case-sensitive. The [docs][4] say:
```
    /**
     * 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) { ... }
```
The second example in **equals** (above) is the only difference from the comparison in **equalsIgnoreCase**.
```
[String][2] string1 = "MYTEXT";
[String][2] string3 = "mytext";
[System][3].out.println("Output: " + string1.equalsIgnoreCase(string3));
Output: true
```
This returns **true** because the comparison is case-independent. All other examples under **equals** remain the same as they are for **equalsIgnoreCase**.
### String compareTo
The **compareTo** method compares two strings lexicographically (i.e., pertaining to alphabetical order) and case-sensitively and returns the lexicographical difference in the two strings. The [docs][4] describe lexicographical order computation as:
```
/**
     * 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) { ... }
```
Let's look at some examples.
```
[String][2] string1 = "A";
[String][2] string2 = "B";
[System][3].out.println("Output: " + string1.compareTo(string2));
Output: -1
[System][3].out.println("Output: " + string2.compareTo(string1));
Output: 1
[/code] [code]
[String][2] string1 = "A";
[String][2] string3 = "a";
[System][3].out.println("Output: " + string1.compareTo(string3));
Output: -32
[System][3].out.println("Output: " + string3.compareTo(string1));
Output: 32
[/code] [code]
[String][2] string1 = "A";
[String][2] string6 = "A";
               
        [System][3].out.println("Output: " + string1.compareTo(string6));
Output: 0
[/code] [code]
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
The behavior of **compareToIgnoreCase** is identical to **compareTo** with one difference: the strings are compared without case consideration.
```
[String][2] string1 = "A";
[String][2] string3 = "a";
[System][3].out.println("Output: " + string1.compareToIgnoreCase(string3));
Output: 0
```
### Objects equals
The **Objects equals** method invokes the overridden **String equals** method; its behavior is the same as in the **String equals** example above.
```
[String][2] string1 = "MYTEXT";
[String][2] string2 = "YOURTEXT";
[System][3].out.println("Output: " + Objects(string1, string2));
Output: false
[/code] [code]
[String][2] string1 = "MYTEXT";
[String][2] string3 = "mytext";
[System][3].out.println("Output: " + Objects(string1, string3));
Output: false
[/code] [code]
[String][2] string1 = "MYTEXT";
[String][2] string6 = "MYTEXT";
[System][3].out.println("Output: " + Objects(string1, string6));
Output: true
[/code] [code]
[String][2] string1 = "MYTEXT";
[String][2] string8 = null;
[System][3].out.println("Output: " + Objects.equals(string1, string8));
Output: false
[System][3].out.println("Output: " + Objects.equals(string8, string1));
Output: false
[/code] [code]
[String][2] string8 = null;
[String][2] string9 = null;
[System][3].out.println("Output: " + Objects.equals(string8, string9));
Output: true
```
The advantage here is that the **Objects equals** method checks for null values (unlike **String equals**). The implementation of **Object equals** is:
```
public static boolean equals([Object][7] a, [Object][7] b) {
return (a == b) || (a != null && a.equals(b));
}
```
### Which method to use?
There are many methods to compare two strings. Which one should you use? As a common practice, use **String equals** for case-sensitive strings and **String equalsIgnoreCase** for case-insensitive comparisons. However, one caveat: take care of NPE (**NullPointerException**) if one or both strings are null.
The source code is available on [GitLab][8] and [GitHub][9].
--------------------------------------------------------------------------------
via: https://opensource.com/article/19/9/compare-strings-java
作者:[Girish Managoli][a]
选题:[lujun9972][b]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]: https://opensource.com/users/gammayhttps://opensource.com/users/sethhttps://opensource.com/users/clhermansenhttps://opensource.com/users/clhermansen
[b]: https://github.com/lujun9972
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/code_javascript.jpg?itok=60evKmGl (Javascript code close-up with neon graphic overlay)
[2]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+string
[3]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+system
[4]: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/String.java
[5]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+exception
[6]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+nullpointerexception
[7]: http://www.google.com/search?hl=en&q=allinurl%3Adocs.oracle.com+javase+docs+api+object
[8]: https://gitlab.com/gammay/stringcomparison
[9]: https://github.com/gammay/stringcompare