3.2 Comparing Strings

The relational operators used to compare primitive types should not be used to compare strings. The reason for this is based on the way that string objects are stored in Java. Suppose that we have written
     String s1 = "Hello";
     String s2 = "Hello"; 
We can represent the result of executing these statements with a diagram.

     Because both sl and s2 refer to strings with identical values, the Java compiler tries to save space by only allocating memory for one copy of the string "Hello" and having both sl and s2 refer to this location.
     On the other hand, if we were to write
     String sl = "Hello";
     String s2 = "He";
     s2 += "llo"; 
then both sl and s2 will still refer to a string with the value "Hello" but now, because we have constructed the two strings in different ways, the Java compiler will probably not realize that they are the same2 and will create two distinct copies of the string. The next diagram illustrates the resulting situation.

     If we write the expression sl == s2, Java evaluates this by comparing the values stored in s1 and s2, not the strings to which s1 and s2 refer. If sl and s2 refer to the same copy of a string (as in our first case), then sl == s2 will have the value true but if they refer to different copies of the same string (as in our second case), then s1 == s2 will have the value false because sl and s2 contain different memory references.
     If we want to compare values of strings rather than the values of references to those strings, we should use methods. Java provides a number of methods for comparing strings. In this section, we will examine only two. In Chapter 9, we examine strings in more detail.

     To test whether or not two string variables are referring to equal string objects, we can use the method equals from the String class. The method tests two strings for equality and returns the value true if the strings are identical and false otherwise. This method is used in a manner that is somewhat different from that used for the methods of the Math class that we saw in Chapter 2. If s1 and s2 are both references to strings, then the expression

s1.equals(s2) 
will have the value true if and only if the values of the two strings are identical.
2We say "probably" because some Java compilers are better than others at detecting this sort of thing.

Example 1

Given the declaration
String s = "Same"; 
then

(a) s.equals("Same") will return true
(b) s.equals("same") will return false because 'S''s'
(c) s.equals("Same ")will return false because of the blank in the string "Same "


The lexicographic order of two strings is, essentially, their dictionary order; it is based on the collating sequence of the characters in the strings. To determine the lexicographic order of a pair of strings, we can use the method compareTo from the String class. In comparing strings, the method proceeds from left to right, character by character, as long as corresponding characters are identical. This process can terminate in one of three ways:

• The end of both strings is reached with all characters equal; the strings are identical.

• The end of one string is reached but the other is not; the shorter string precedes the longer string.

• A character in one string differs from the corresponding character in the other string; the string having the character earlier in Java's collating sequence precedes the other string.

The method compareTo returns an integer value that indicates the lexicographic ordering of two strings. If s1 and s2 are both references to strings, then the expression

s1.compareTo(s2)
has the value zero if s1 is identical to s2, a negative value if s1 precedes s2, and a positive value if s1 follows s2.

Example 2

(a) "cab".compareTo("car") < 0 because 'b' < 'r'
(b) "Car".compareTo("car") < 0 because 'C' < 'c'
(c) "27".compareTo("186") > 0 because '2' > '1'
(d) "car".compareTo ("cart") < 0 because "car" is only the first part of "cart"

The compareTo method can be used to implement any of the six relational operators (<, <=, >, >=, ==, or !=) by writing expressions of the form

<string1>.compareTo(<string2>) <op> 0
where <op> is one of the six relational operators. For example, if s1 and s2 are both references to strings, then the expression
s1.compareTo(s2) <= 0
has the value true if and only if the string s1 precedes or is identical to the string s2.

Exercises 3.2

  1. For each of the following pairs of strings, state, with reasons, which string precedes the other.
    1. "cat" and "dog"
    2. "cat" and "Cathy"
    3. "X " and " X"
    4. "cab" and "CAR"
    5. "XX" and "X X"
    6. "XY" and "XY "
    7. "375" and "84"
    8. "" and " "
  2. State the value of each expression.
    1. "one".equals("one ")
    2. "two".equa1s("2")
    3. "Three".equa1s("Three")
    4. "four".equa1s("for")
  3. State whether the value of the expression is negative, zero, or positive.
    1. "for".compareTo("fore")
    2. "fore".compareTo("force")
    3. "force".compareTo("Force")
    4. "Force".compareTo("Farce")
    5. "Farce".compareTo("Fare")
    6. "Fare".compareTo ("far")
    7. "far".compareTo("far")
    8. "far".compareTo("far ")
  4. Suppose that s1 and s2 are variables of type String. Write an expression of the form s1.compareTo(s2) <op> 0 that will have the value true if and only if the stated condition is true.
    1. s1 is identical to s2
    2. s1 precedes s2
    3. s1 is identical to or follows s2
    4. s1does not follow s2