How to compare Strings in Java?

The == operator says that the Strings are different, and they store the same literal value, See example:

public class TesteString {
    public static void main(String[] args) {

        String str1 = "teste";
        String str2 = "Oteste".substring(1);

        System.out.println("str1: " + str1 + ", str2: " + str2);
        if(str1 == str2) {
            System.out.println("str1 igual a str2");
        }
        else {
            System.out.println("str1 diferente de str2");
        }
    }
}

Result:

str1: teste, str2: teste
str1 diferente de str2

How to compare the literal value of Strings?

 58
Author: Math, 2014-02-03

4 answers

Playing with the == and the pool of strings

Java uses a mechanism called string interning, putting the Strings in a pool to try to store only one copy of each string in memory.

When Java finds string literals in the code, it always returns the same String instance, which points to an entry in the JVM's internal pool. Thus, it is quite possible to use the operator == to compare two variables that receive string literals:

String literal = "str";
String outraLiteral = "str";

System.out.println(literal == outraLiteral); //exibe true

Inclusive, because Java treats string literals as instances it is possible to compare a literal directly, like this:

System.out.println(literal == "str"); //também retorna true

On the other hand, we cannot rely on the comparison operator when we do not know how the String was created, since it is possible to create other instances in various ways. Example:

String novaInstancia = new String("str");
System.out.println("str" == novaInstancia); //retorna false

The above code creates a new String instance, which is not the same returned by the JVM for the literal "str".

But, however, in the meantime, that doesn't mean we have two entries of "str" in Java's pool. How can we verify this? Using the String.intern() method, which returns a reference to the String that is in the pool. Example:

String novaInstancia = new String("str");
System.out.println("str" == novaInstancia.intern()); //retorna true

Applying this to in the example of the question, we would have:

public class TesteString {
    public static void main(String[] args) {

        String str1 = "teste";
        String str2 = "Oteste".substring(1);

        System.out.println("str1: " + str1 + ", str2: " + str2);
        if(str1 == str2.intern()) {
            System.out.println("str1 igual a str2");
        }
        else {
            System.out.println("str1 diferente de str2");
        }
    }
}

And the result:

Str1: heads, str2: heads

Str1 equals str2

All very Interesting. But what if we created a string in a stunning way?

StringBuilder sb = new StringBuilder();
sb.append('s');
sb.append('t');
sb.append('r');
System.out.println("str" == sb.toString().intern()); //continua sendo true

But what about equals()?

If the comparison with == is faster than the equals() method, should we abandon the equals() and use the intern() everywhere? The answer is not .

Not all Strings are internalized in the pool immediately. When we call the intern() method, if it is not there, then Java will add it. The problem is that once in the pool a String goes to permanent memory and will no longer be collected by the garbage collector.

When you want speed and the set of values is relatively small, using the intern() method can be advantageous. But if we use this feature, for example, for processing text files, XML, databases, then we will soon see a OutOfMemoryError.

Also, adding A Strings in pool can also be an "expensive"operation. In addition, it is necessary to check if the String is already there is, Java will probably have to treat concurrent accesses.

And, finally, a big disadvantage is the code becoming more prone to bugs ( error prone ), since it is necessary that the developer always put the intern() when necessary.

Other ways to compare

Going a little further than the exact comparison of Strings, we have other interesting ways of comparison:

case insensitive (not considering capital and lowercase)

System.out.println("STR".equalsIgnoreCase("str")); //retorna true

A string contained in another

System.out.println("###STR###".contains("STR")); //retorna true

Which string is "bigger" than the other?

System.out.println("str1".compareTo("str2")); //retorna -1, pois "str1" é menor que "str2"

Or:

System.out.println("str1".compareToIgnoreCase("STR2")); //retorna -1, ignorando a capitalização

Method compareTo returns:

  • 1 if the first String is greater than the second
  • 0 if they are equal
  • -1 if the first String is less than the second

Starts with...

System.out.println("str1".startsWith("str")); //returna true, pois "str1" começa com "str"

Ends with...

System.out.println("str1".endsWith("r1")); //return true, pois "str1" termina com "r1"

Regular expression

System.out.println("str2".matches("\\w{3}\\d")); //return true, pois corresponde à expressão regular

Is empty?

String str1 = "";
System.out.println(str1.isEmpty());
System.out.println(str1.length() == 0);
System.out.println(str1.equals(""));

Particularly I prefer the first method for Java >= 6 and the second for earlier versions.

 49
Author: utluiz, 2020-06-11 14:45:34

Variables of type String store object references, not a string literal value. Then == compares the reference, and will only return true if both variables are referencing the same object.

.equals() it is a method of Class Object, which compares the values of literals stored by objects, therefore, this method should be used to compare values of the literal of variables of type String.

public class TesteString {
    public static void main(String[] args) {

        String str1 = "teste";
        String str2 = "Oteste".substring(1);

        System.out.println("str1: " + str1 + ", str2: " + str2);
        if(str1.equals(str2)) { //perceba a diferença aqui
            System.out.println("str1 igual a str2");
        }
        else {
            System.out.println("str1 diferente de str2");
        }
    }
}

Result:

str1: teste, str2: teste
str1 igual a str2 //agora o resultado dá comparação diz que são iguais

References: String (Java Platform SE 7 ) / Object

 39
Author: Math, 2014-02-03 15:27:59

Only complementing @Math's answer

Objects of Class String have an interesting particularity. the JVM keeps a string pool , where it stores the Strings that have passed in your code, to avoid having to keep loading repeated Strings, but how does it work?

A String will go to the pool if you instantiate the String literally, like this:

String str1 = "text";

The value "text" is now stored in the pool

On the other hand, if you instantiate with the keyword new, the value used will not be that of the pool, even if it is equal.

String str2 = new String("text");

What can be seen with a simple test.

System.out.println(str1 == str2); // Imprime false

Now if you want the String to be the same as the pool you can use the intern() method, the documentation from it says the following:

Returns a canonical representation for the string object. A pool of strings, initially empty, is maintained privately by the Class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

That is, if an object with the value of String already exists in the pool , it is returned, if it does not exist, this value is added there, and the reference that was added is returned. And we can prove it with another simple test.

System.out.println(str1 == str2.intern());
 14
Author: Rodrigo Sasaki, 2014-02-03 17:57:13

Use Only the .equals ().

Example:

String a = "1";
String b = "2";

if(a.equals(b))
return true;
 3
Author: Luiz, 2015-04-28 21:09:34