JavaRush /Java Blog /Random EN /Equals in Java and String compare - String comparison

Equals in Java and String compare - String comparison

Published in the Random EN group
Hello! Today we will talk about a very important and interesting topic, namely, comparing objects to each other with equals() in Java. Indeed, in what cases in Java will Object A be equal to Object B ? Equals and string comparison - 1Let's try to write 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
Yes, stop. And why, in fact, these two machines are not equal? We gave them the same properties, but the result of the comparison is false. The answer is simple. The operator ==compares not properties of objects, but references. Even if two objects have 500 identical properties, the result of the comparison will still be false. After all, links car1point car2 to two different objects , to two different addresses. Imagine a situation where people are compared. There is probably a person in the world who has the same name, eye color, age, height, hair color, etc. as you. That is, you are similar in many ways, but still you are not twins, and even more so you are not the same person. Equals and string comparison - 2Approximately such logic is applied by the operator==when we use it to compare two objects. But what if you need different logic in your program? For example, if your program simulates DNA analysis. She must compare the DNA code of two people, and determine that they are twins.
public class Man {

   int 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 == man2);
   }
}
Console output:

false
It is logical that the result is the same (after all, we didn’t really change anything), but now it doesn’t suit us! Indeed, in real life, DNA analysis is a 100% guarantee that we have twins. But our program and operator ==tell us otherwise. How can we change this behavior and make sure that if the DNA analyzes match, the program will give the correct result? For this purpose, a special method was created in Java - equals() .

Equals() method in Java

Like the method toString()we discussed earlier, equals() belongs to the class Objectitself, the most basic class in Java, from which all other classes derive. However, equals() by itself will not change the behavior of our program in any way:
public class Man {

   String dnaCode;

   public static void main(String[] args) {

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

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

       System.out.println(man1.equals(man2));
   }
}
Console output:

false
Exactly the same result, so why do we need this method? :/ It's simple. The fact is that now we have used this method as it is implemented in the class itself Object. And if we go into the class code Objectand see how this method is implemented in it and what it does, we will see:
public boolean equals(Object obj) {
   return (this == obj);
}
That's the reason why our program's behavior hasn't changed! Inside the class's equals() method Objectis the same reference comparison, ==. But the trick of this method is that we can override it. Overriding means writing your own equals() method in our class Manand making it behave the way we want! Right now, we're not happy that checking man1.equals(man2), in fact, does the same thing as man1 == man2. Here is what we will do in such a 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
Quite a different result! By writing our own equals() method instead of the standard one, we have achieved the correct behavior: now if two people have the same DNA code, the program tells us: “DNA analysis showed that they are twins” and returns true! By overriding the equals() method in your classes, you can easily create the desired object comparison logic. We have touched upon the comparison of objects only in general terms. We will have a separate large lecture on this topic ahead of us (you can read it quickly now, if you are interested).

String compare in Java - String comparison

Why do we treat string comparison separately from everything else? Well, in fact, strings in programming are a whole different story. First, if we take all Java programs written by humanity, about 25% of the objects in them are exactly them. Therefore, this topic is very important. Secondly, 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 site to learn Java!";
       String s2 = new String("CodeGym is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Console output:

false
But why false? The strings are exactly the same, word for word :/ You can guess: this is because the operator == compares references! After all, s1they s2have different addresses in memory. If this thought occurred to you, then let's remake our example:
public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best site to learn Java!";
       String s2 = "CodeGym is the best site to learn Java!";
       System.out.println(s1 == s2);
   }
}
Now we also have two links, but the result has changed to the opposite: Console output:

true
Completely confused? :) Let's figure it out. The operator ==does indeed compare addresses in memory. This rule always works and there is no need to doubt it. So if s1 == s2it returns true, these two strings have the same address in memory. And indeed it is! It's time to get acquainted with a special area of ​​memory for storing strings - a string pool ( String pool) Equals and string comparison - 3A string pool is an area for storing all the string values ​​\u200b\u200bthat you create in your program. Why was it created? As mentioned earlier, strings take up a huge portion of all objects. In any large program, a lot of lines are created. In order to save memory and needString Pool- a line with the text you need is placed there, and in the future, newly created links refer to the same memory area, there is no need to allocate additional memory each time. Every time you write String = “........”, the program checks if there is a line with that text in the string pool. If there is, a new one will not be created. And the new link will point to the same address in the string pool where that string is stored. So when we wrote in the program
String s1 = "CodeGym is the best site to learn Java!";
String s2 = "CodeGym is the best site to learn Java!";
the link s2points exactly to the same place as s1. The first command created a new line in the string pool with the text we needed, and when it came to the second, it simply referred to the same memory area as s1. You can make at least 500 more lines with the same text, the result will not change. Stop. But why then did this example not work for us earlier?
public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best site to learn Java!";
       String s2 = new String("CodeGym is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
I think, intuitively, you already guess what the reason is :) Try to guess before reading further. You can see that these two lines were created differently. One - with the help of the operator new, and the second without it. This is precisely the reason. The new operator, when creating an object, forces it to allocate a new area in memory for it . And a string created with newdoes not fall into String Pool: it becomes a separate object, even if its text exactly matches the same string from String Pool'a. That is, if we write code like this:
public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best site to learn Java!";
       String s2 = "CodeGym is the best site to learn Java!";
       String s3 = new String("CodeGym is the best site to learn Java!");
   }
}
In memory, it will look like this: Equals and string comparison - 4And each time a new object is created, newa new area will be allocated in memory, even if the text inside the new lines is the same! We sort of figured out the operator ==, but what about our new friend - the equals () method?
public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best site to learn Java!";
       String s2 = new String("CodeGym is the best site to learn Java!");
       System.out.println(s1.equals(s2));
   }
}
Console output:

true
Interesting. We know exactly what s1and s2point to different areas in memory. But still, the equals() method says they are equal. Why? Remember how we talked earlier about how you can override the equals() method in your class to compare objects the way you want? StringThey did the same with the class . It has an overridden equals() method. And it does not compare links, but the sequence of characters in strings. And if the text in the lines is the same, it doesn't matter how they were created and where they are stored: in the string pool, or in a separate memory area. The result of the comparison will be true. By the way, Java allows you to correctly compare strings without regard to case. In a normal situation, if you write one of the lines, for example, in caps, then the result of the comparison will be false:
public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best site to learn Java!";
       String s2 = new String("CODEGYM - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Console output:

false
For this case, the class Stringhas a method equalsIgnoreCase(). If in your comparison the main thing is the sequence of specific characters, and not their case, you can apply it. For example, this would be useful when comparing two email addresses:
public class Main {

   public static void main(String[] args) {

       String address1 = "Moscow, Academician Korolev street, 12";
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
In this case, it is obvious that we are talking about the same address, so using the method equalsIgnoreCase()will be the right decision.

String.intern() Method

The class Stringhas another tricky method - intern(); The method intern()works directly with String Pool'om. If you call a method intern()on some string, it:
  • Checks if there is a line with such text in the string pool
  • If it exists, it returns a link to it in the pool
  • If not, puts a string with this text into the string pool and returns a link to it.
By applying the method intern()to the string reference created with new, we can compare it with the string reference from String Pool'a via the ==.
public class Main {

   public static void main(String[] args) {

       String s1 = "CodeGym is the best site to learn Java!";
       String s2 = new String("CodeGym is the best site to learn Java!");
       System.out.println(s1 == s2.intern());
   }
}
Console output:

true
Previously, when we compared them without intern(), the result was false. Now the method intern()checks if there is a line with the text "CodeGym is the best site for learning Java!" in the string pool. Of course, it is there: we created it when we wrote
String s1 = "CodeGym is the best site to learn Java!";
A check was made that the reference s1and the reference returned by the method s2.intern()point to the same area in memory, and, of course, this is the case :) Summing up, remember and use the main rule: To compare strings, ALWAYS use the equals() method! When comparing strings, you almost always mean comparing their text, not links, memory areas, and so on. The equals() method does exactly what you need. Equals and string comparison - 5Here are some links for you to explore on your own:
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION