How to correctly compare Strings (and objects) in Java?

I am creating a mini game in which the user tries to guess a name. But when I want to compare two text strings to see if they are equal it doesn't seem to work.

final String miNombre = "Jordi";
Scanner input = new Scanner(System.in);
System.out.println("Adivina mi nombre: ");

while (true) {
    String intento = input.next();
    if(intento == miNombre) {
        System.out.println("Acertaste!");
        break;
    } else {
        System.out.println("Intentalo de nuevo!");
    }
}

Output:

Adivina mi nombre: 
manuel
Intentalo de nuevo!
jordi
Intentalo de nuevo!
Jordi
Intentalo de nuevo!
 86
Author: Jordi Castilla, 2015-12-02

12 answers

On Java only primitive types (Described in JLS (§4.2), for example int or char) are compared with ==, the Strings (and other objects) in Java are compared between them with the method equals.

String#equals(Object)

Compares this String with the specified object. The result is true if, and only if the argument is not null and is an object of type String representing the same sequence of characters as this object.


  • JLS (§15.21.3) while == can be used to compare type References String, an equality test determines whether the two operands refer to the same object String. The result is false if the operands are different String objects, even if they contain the same sequence of characters.

Therefore your comparison should ser:

if(miNombre.equals(intento)) {

Output:

Adivina mi nombre: 
manuel
Intentalo de nuevo!
Jordi
Acertaste!

Clarifications:

  • I have put the variable miNombre at the beginning of the comparison to avoid a NullPointerException if intento == null (if, comparisons with null are also made with ==).

    As an extra: if null is a valid value in the representation (and therefore we want to avoid a NPE), Objects.equals it is available from Java 7 and takes care of returning true if both are null or false if only one is true.

  • In this case the method can be used String#equalsIgnoreCase(Object) ignore MAYUSCULAS or MINUSCULAS when comparing:

    if(miNombre.equalsIgnoreCase(intento)) {       
    
  • JLS (§15.21) equality operators (== and !=) can be used to compare two operands that are convertible (§5.1.8) of numeric type, or the two operands of Type boolean or Boolean or two operands that > are of type type null. All other cases cause a compile-time error.

 110
Author: Jordi Castilla, 2015-12-16 08:07:07

From Java 7 it is possible to compare the equality of two strings using the method equals of the Class java.util.Objects. This is:

String a = ...
String b = ...

if (Objects.equals(a, b)) {
    // iguales
} else {
    // diferentes
}

Since a.equals(b) or b.equals(a) can throw java.lang.NullPointerException if a is null or b is null respectively, using this path, a or b can be null without any risk.

If you are using Java 6 (or lower), starting from the code of this class, we can rewrite our if of the following way:

if (a == b || (a != null && a.equals(b))) {
    // iguales
} else {
    // diferentes
}
 33
Author: Paul Vargas, 2015-12-03 04:13:06
  • The "= = " operator compares two references, i.e. returns true if both objects occupy the same memory position.

  • The "equals" method compares the values of objects.

 25
Author: Jose4Linux, 2017-08-10 02:50:18

In the language Java the function equals() is used to compare strings, the operator should never be used== .

String nombre = "elenasys";

if (nombre.equals("elenasys")) { //Correcto para comparar strings!
    ...
}

if (nombre == "elenasys") {   //Incorrecto para comparar strings!
    ...
}

This is a common mistake in New developers.

 19
Author: Jorgesys, 2017-05-08 19:05:46

To complement the other answers I will tell you that there is no rule to compare the equality of a string, both the method .equals() and the == operator are fully valid, the difference depends on what you want to compare or what your intention really is when you want to compare two objects String, (by reference or by value).

Strings are objects like any other but there are big and subtle differences that separate it from other objects, first of all to a string the you can initialize in these two ways.

String usandoLiteral = "Mi literal"; // Por medio de un literal
String usandoNew = new String("Con operador new"); // Utilizando el operador clasico new

In both cases an object is being created, the absence of the new operator in the first example is only a shortcut (so it looks more natural).

Now You have to understand how Java manages strings, in Java there is the String Pool this is a memory space reserved for storing strings, an application normally makes a strong use of Strings and only these can occupy up to 40% of the memory in runtime and many of these string's are repeated for example 'A' 'in' ' la ' etc.to optimize this Java collects all these strings as literals in a location of the JVM and reuses the repeated literals to optimize memory usage, so if you store the literal "carlos" in two variables, Java will reuse this literal.

For this reason if you declare the following variables String and initialize them with the same literal. (remember that you are creating two Objects)

String nombre = "carlos";
String nombre2 = "carlos";

The comparison with the = = operator will return true, because the String Pool recycles the literal "carlos" and therefore they are the same reference, therefore it is completely valid to make the comparison.

Boolean sonIguales = nombre == nombre2; // sonIguales tiene el valor true

The String Pool only recycles and stores literals, this means that if you create a string as follows

String nombre3 = new String("carlos");

Not being initialized with a java literal will not store it in the String Pool nor will there be recycling therefore it will be removed by the Garbage Collector, if this is so then the following comparison will result in false.

Boolean esIgualAlTercero = nombre == nombre3; // esIgualAlTercero tiene el valor false.

This is the reason why when you do the comparison with the = = operator sometimes it will give you true and sometimes it will give you false even though you compare the same value in the string.

The method .equals you use it when you want to compare the string by value or character by character, it is a safe way to do the string comparison since remember that as in the first example we technically did a value comparison with the = = operator due to the peculiarity of the String Pool.

An additional note in case you're wondering, if when initializing a string by literal the value is stored in the String Pool that happens when I modify the string?

Because that's another point, strings in Java are immutable, this means that you can not modify their value for example adding more characters to a string value and Java does not it provides no API to modify a String directly. (however Java provides an API to be able to do it indirectly)

For example if I want to add the last name to my variable (name) what I can do is re assign to the variable (name) a new string that I will construct by concatenating the original value with the last name in this way.

nombre = nombre + " lucero"; 

This what it does is create a new value "carlos lucero" and assign this value to the string name.

Now What if I now compare 'name' with a new variable containing the same value as' name ' but assigned as literal?

String nombreCompleto = "carlos lucero";
Boolean esNombreCompletoIgual = nombreCompleto == nombre; // recuerda que nombre ahora tiene el valor "carlos lucero"

As the variable (name) was re-assigned to a new value was not created by means of a literal because now the variable (name) is no longer in the String Pool for your reference is not recycled and the comparison with the variable (fullname) if it was created by means of the literal will result False.

Finally Java provides an API to solve the problem of immutability of strings, this API is exposed by the Class StringBuilder.

 14
Author: Carlos Lucero, 2017-01-18 07:10:35

As already mentioned, the = = operator finds in the case of primitives that the values are identical, in the case of objects that the reference points to the same object.

Need to explain a little about the method equals () All classes in Java are subclasses of Object , object comes with a default statement of equals().

If I declare a new class, other users of my class expect me to implement a equals(Object o) method that it implies that two objects are considered equal. That doesn't necessarily mean they are, and may require comments in the documentation. An example:

public class Point(){
    private int x;
    private int y;

    public Point(intx, int y){
        this.x=x;
        this.y=y;
    }

    public int getX() {return x;}

    public int getY() {return x;}

    @Override
    public boolean equals(Object o){
        return o instanceof Point && ((Point)o).getX()==x && ((Point)o).getY()==y;
    }
}

If I declare a subclass of point tagged as:

public class NamedPoint extends Point{

    private String etiqueta;

    public NamedPoint(int x, int y, String etiqueta){
        super(x,y);
        this.etiqueta=etiqueta;
    }

    public String getEtiqueta(){ return etiqueta }
}

Should comment that two Namedpoints are considered equal if the coordinates match, independent of the tag.

Eye, just overwriting the method doesn't ensure consistency in my logic. If I overwrite equals in NamedPoint to also consider tags, I'm left with the following problem:

Point point = new Point(3,6);
Point otroPoint = new NamedPoint(3,6,"Foo");
boolean equals1 = point.equals(otroPoint); // resultado true
boolean equals2 = otroPoint.equals(point); // resultado false

To escape this ambiguity you can compare classes instead of using instanceof:

    @Override
    public boolean equals(Object o){
        return this.getClass().equals(o.getClass()) 
            && ((Point)o).getX()==x && ((Point)o).getY()==y;
    }

Summary: there are dragons on the issue of equality.

 11
Author: Stefan Nolde, 2017-01-08 07:31:43

The == operator usually works when the variable has already been initialized, because it compares the internal representations, but the most correct is to compare using the equals method that is inherited from the Object class.

Comparing them using equals is almost always the best solution

String cadena1="Hola";
String cadena2="Hola";
System.out.println(cadena1.equals(cadena2)); //funciona

String cadena1;
String cadena2="Hola";
System.out.println(cadena1.equals(cadena2)); //funciona

But despite this you could have problems if your virtual machine is smaller than Tiger, because in aciagas implementations a string defined as null was not the same as a string empty.

String cadena1="";
String cadena2=null;
String cadena3;
System.out.println(cadena1.equals(cadena2).equals(cadena3));

So for those cases you can use the comparison using the operator ==

String cadena1="Hola";
String cadena2="Hola";
System.out.println(cadena1 == cadena2); //funciona porque ya están inicializadas

Or having a lot of reservation, comparing the internal representations.

String cadena1="Hola";
String cadena2="Hola";
System.out.println(cadena1.intern() == cadena2.intern()); //son iguales solamente si cadena1.equals(cadena2)
 10
Author: Ruslan López, 2015-12-03 15:46:51

"== " is used for an Integer ,Char, Object, or null, among others, better use equals or equalsIgnoreCase:

 final String miNombre = "Jordi";
Scanner input = new Scanner(System.in);
System.out.println("Adivina mi nombre: ");

while (true) {
    String intento = input.next();
    if(intento.equalsIgnoreCase(miNombre)) { //Tu puedes usar equals para que sea igual y equalsIgnoreCase para que se igual ignorando las mayúsculas && minúsculas, es decir que por mas que escribas JoRdI va a ser "true".
        System.out.println("Acertaste!");
        break;
    } else {
        System.out.println("Intentalo de nuevo!");
    }
}
 10
Author: Java doub, 2016-08-20 04:22:31

The correct way to compare 2 Strings is by using the function equals(), which is to compare the 2 strings and equalsIngnoreCase() which is the same but ignoring case.

Try with:

if(intento.equalsIgnoreCase(miNombre)){
     System.out.println("Has Acertado");
}
else{
     System.out.println("Incorrecto");
}
 9
Author: Alexis Rodriguez, 2016-10-15 22:27:09

For primitive types only the comparison = = is valid in general. For objects you should use comparison methods like equals() which could be valid for Strings. For other types of objects this type of comparison might not be valid.

With = = references and non-content of in-memory objects are compared.

 9
Author: joseluque, 2016-12-14 01:30:09

In java the correct way to compare Strings is by using the equals method which is inherited from the object

Example:

String str1 = "hola"
String str2 = new String("hola");
String str3 = "hola";
System.out.println(str1 == str2); //falso 
System.out.println(str1 == str3); //verdadero
System.out.println(str1.equals(str2)); //verdadero
System.out.println(str2.equals(str3)); //verdadero

When declaring a String this way : String str = "String"; the object is a literal (value declared at the time of writing the code) and is stored in the String pool (Pool where strings are stored once and are read several times by literals)

So:

"cadena" es distinto a new String("cadena") ;

Since the latter is it generates at runtime and is not in the String pool.

 8
Author: Jose Felipe Charbel Pavez Gass, 2017-03-08 15:17:17

You can implement the String method.equals ( "" ); which the same Java API brings as well as you must implement the corresponding validations as they are: perform the string.trim (); to the text you want to validate since a space also counts when comparing. this method what it does is remove the spaces at the end and beginning of the string. you can also include string.lengt(); to perform your validations everything depends on your needs. greeting example Simple:

String micadena="Hola mundo";
String cadenaGuardada="Hola mundo";

if(micadena.equals(cadenaGuardada))
return "iguales";
else
return "No son iguales";
 5
Author: Jose Antonio Dominguez Garcia, 2017-09-13 19:14:33