CodeGym /Java Blog /Java Objects /Compare String and Equals comparisons in Java
Author
Milan Vucic
Programming Tutor at Codementor.io

Compare String and Equals comparisons in Java

Published in the Java Objects group
Hi! Today we will talk about a very important and interesting topic, namely, comparing objects with objects (Compare Strings and Equals). So in Java, when exactly would object A be equal to object B? Let's try writing an example:

public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {
      
       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
Console output: false Wait, stop. Why is it that these two cars are not equal? We assigned them the same properties, but the result of the comparison is false. The answer is simple. The == operator compares object references, not object properties. Two objects could even have 500 fields with identical values, but comparing them would still yield false. After all, references car1 and car2 point to two different objects, i.e. to two different addresses. Imagine a situation where you're comparing people. Certainly, somewhere in the world there is a person who shares your same name, eye color, age, height, hair color, etc. That makes you similar in many respects, but you're still not twins — and you're obviously not the same person.
Equals and string comparisons - 2
The == operator uses approximately this same logic when we use it to compare two objects. But what if you need your program to use different logic? For example, suppose your program performs DNA analysis. It compares the genetic code of two people, and determines whether they are twins.

public class Man {

   int geneticCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.geneticCode = 1111222233;

       Man man2 = new Man();
       man2.geneticCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
Console output: false We get the same logical result (because we didn't change much), but now that logic is no good! After all, in real life, DNA analysis should give us a 100% guarantee that we've got twins standing in front of us. But our program and the == operator tell us the opposite. How do we change this behavior and make sure the program outputs the correct result when the DNA matches? Java has a special method for this: equals(). Like the toString() method, which we discussed earlier, equals() belongs to the Object class — the most important class in Java, the class from which all other classes derive. But equals() doesn't change our program's behavior all by itself:

public class Man {

   String geneticCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.geneticCode = "111122223333";

       Man man2 = new Man();
       man2.geneticCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
Console output: false Exactly the same result, so what do we need this method for? :/ It's all simple. The issue here is that we're currently using this method as it is implemented in the Object class. And if we go into the code of the Object class and look at the method's implementation, this is what we'll see:

public boolean equals(Object obj) {
   return (this == obj);
}
That's the reason why the program's behavior hasn't changed! The very same == operator (which compares references) is used inside the equals() method of Object class. But the trick with this method is that we can override it. To override means to write your own equals() method in our Man class, giving it the behavior we need! At present, we don't like the fact that man1.equals(man2) is essentially equivalent to man1 == man2. Here's what we'll do in this situation:

public class Man { 

   int dnaCode; 

   public boolean equals(Man man) { 
       return this.dnaCode ==  man.dnaCode; 

   } 

   public static void main(String[] args) { 

       Man man1 = new Man(); 
       man1.dnaCode = 1111222233; 

       Man man2 = new Man(); 
       man2.dnaCode = 1111222233; 

       System.out.println(man1.equals(man2)); 

   } 
} 
Console output: true Now we get an entirely different result! By writing our own equals() method and using it instead of the standard one, we've produced the correct behavior: Now if two people have the same DNA, the program reports "DNA analysis has proven they are twins" and returns true! By overriding the equals() method in your classes, you can easily create whatever object comparison logic you need. In fact, we've only just touched on object comparison. Ahead of us, there is still a big standalone lesson on this topic (you skim over it now if you're interested).

Comparing strings in Java

Why are we considering string comparisons separately from everything else? The reality is that strings are a subject in their own right in programming. First, if you take all the Java programs ever written, you'll find that about 25% of the objects in them are strings. So this topic is very important. Second, the process of comparing strings is really very different from other objects. Consider a simple example:

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1 == s2);
   }
}
Console output: false But why did we get false? After all, the strings are exactly the same, word for word :/ You might have guessed the reason: it's because the == operator compares references! Clearly, s1 and s2 have different addresses in memory. If you thought of that, then let's rework our example:

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = "CodeGym is the best website for learning Java!";
       System.out.println(s1 == s2);
   }
}
Now we again have two references, but the result is the exact opposite: Console output: true Helplessly confused? Let's figure out what's going on. The == operator really does compare memory addresses. This is always true and you don't need to doubt it. That means that if s1 == s2 returns true, then these two strings have the same address. And indeed this is true! It's time to introduce you to a special area of memory for storing strings: the string pool
Equals and string comparisons - 3
The string pool is an area for storing all the string values you create in your program. Why was it created? As we said before, strings represent a huge percentage of all objects. Any large program creates a lot of strings. The string pool was created to save memory: strings are placed there and then subsequently created strings refer to the same area of memory—there is no need to allocate additional memory each time. Every time you write String = "........" the program checks if there is an identical string in the string pool. If there is, then a new string won't be created. And the new reference will point to the same address in the string pool (where the identical string is located). So when we wrote

String s1 = "CodeGym is the best website for learning Java!";
String s2 = "CodeGym is the best website for learning Java!";
s2 points to the same place as s1. The first statement creates a new string in the string pool. The second statement simply refers to the same area of memory as s1. You could make another 500 identical strings and the result wouldn't change. Wait a minute. If that's true, then why didn't this example work before?

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1 == s2);
   }
}
I think your intuition has already told you the reason =) Try to guess before reading further. You can see that these two strings were declared in different ways. One with the new operator, and the other without it. Herein lies the reason. When the new operator is used to create an object, it forcefully allocates a new area of memory for the object. And a string created using new doesn't end up in the string pool — it becomes a separate object, even if its text perfectly matches a string in the string pool. That is, if we write the following code:

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = "CodeGym is the best website for learning Java!";
       String s3 = new String("CodeGym is the best website for learning Java!");
   }
}
In memory, it looks like this:
Equals and string comparisons - 4
And every time you create a new object using new, a new area of memory is allocated, even if the text inside the new string is the same! It seems we've figured out the == operator. But what about our new acquaintance, the equals() method?

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1.equals(s2));
   }
}
Console output: true Interesting. We are certain that s1 and s2 point to different areas in memory. But the equals() method still tells us they are equal. Why? Remember we previously said that the equals() method could be overridden to compare objects however we want? That's just what they've done with the String class. It overrides the equals() method. And instead of comparing references, it compares the sequence of characters in the strings. If the text is the same, then it doesn't matter how they were created or where they are stored: whether in the string pool or a separate area of memory. The result of the comparison will be true. By the way, Java lets you perform case-insensitive string comparisons. Normally, if one of the strings has all uppercase letters, then the result of the comparison will be false:

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CODEGYM IS THE BEST WEBSITE FOR LEARNING JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Console output: false For case-insensitive comparisons, the String class has the equalsIgnoreCase() method. You can use it if you only care about comparing the sequence of specific characters rather than the letter case. For example, this could be helpful when comparing two addresses:

public class Main {

   public static void main(String[] args) {

       String address1 = "2311 Broadway Street, San Francisco";
       String address2 = new String("2311 BROADWAY STREET, SAN FRANCISCO");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
In this case, we're obviously talking about the same address, so it makes sense to use the equalsIgnoreCase() method.

The String.intern() method

The String class has one more tricky method: intern(); The intern() method works directly with the string pool. If you call the intern() method on some string:
  • It checks whether there is a matching string in the string pool
  • If there is, it returns the reference to the string in the pool
  • If not, it adds the string to the string pool and returns a reference to it.
After using the intern() method on a string reference obtained using new, we can use the == operator to compare it with a string reference from the string pool.

public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best website for learning Java!";
       String s2 = new String("CodeGym is the best website for learning Java!");
       System.out.println(s1 == s2.intern());
   }
}
Console output: true When we compared these strings previously without intern(), the result was false. Now the intern() method checks whether the string "CodeGym is the best site for learning Java!" is in the string pool. Of course, it is: we created it with

String s1 = "CodeGym is the best website for learning Java!";
We check whether the s1 and the reference returned by s2.intern() point to the same area of memory. And of course, they do :) In summary, memorize and apply this important rule: ALWAYS use the equals() method to compare strings! When comparing strings, we almost always mean to compare their characters rather than references, areas of memory, or anything else. The equals() method does exactly what you need. To reinforce what you learned, we suggest you watch a video lesson from our Java Course

More reading:

Comments (89)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Joe Lobaton Level 4, Colombia
17 March 2024
cada vez aprendo más y de una forma tan clara, muchas gracias...
Henry Lee Level 6, Tokyo, Japan
5 September 2023
Marvelous example! I want to give all my praise to Mr. Milan. And one more comment: CodeGym is the best website for learning Java!
David Level 6, Spain
4 May 2023
Excelente artículo, de gran ayuda, gracias!!!
Ola Level 7, Huai Khwang, Thailand
21 March 2023
So nice and clear article! Thanks!
Buns Level 11, Changsha, China
21 March 2023
great!
Super Ego Level 14, Wu Han, China
27 January 2023
读下来好费劲但很有收获,好好学英语的重要性,哎😢
Siyanda Dlamini Level 7, Durban, South Africa
11 March 2022
Wow this is beautifully explained. Java is really an interesting language. Code gym makes complicated concepts easy to understand
cv Level 5, United States of America, United States
19 November 2021
Why is this invalid? It is supposed to check the string pool for the string value is what i assume. Help me understand this. public class Man { String geneticCode; public static void main(String[] args) { Man man1 = new Man(); man1.geneticCode = "111122223333"; Man man2 = new Man(); man2.geneticCode = "111122223333"; System.out.println(man1.intern()== man2.intern()); } }
Folpo Level 10, Trieste, Italy
4 November 2021
hi everyone, i have one question: in the first example with car, if instead of System.out.println(car1 == car2); --> FALSE i write System.out.println(car1.model == car2.model); i'm expecting TRUE. is it right?
sachin Level 7, Singapore, Singapore Expert
3 July 2021
Can anyone please help me understand the reason why it is returning different result. public class Solution { String geneticCode; public boolean equalss(Solution man) { return this.geneticCode == man.geneticCode; } public static void main(String[] args) { Solution man1 = new Solution(); man1.geneticCode = "111122223333"; Solution man2 = new Solution(); man2.geneticCode = "111122223333"; System.out.println(man1.equals(man2)); System.out.println(man1.equalss(man2)); } } false true ----------------- I am not able to understand how equals function and equalss functions are different where equals function does underneath the same thing. below are the equals method of string class and override method created: public boolean equals(Object obj) { return (this == obj); } public boolean equals(Solution man) { return this.geneticCode == man.geneticCode; } i am confused of the internal working on this == obj. and this.geneticCode == man.geneticCode;