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 with each other equals() in Java. And 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
Okay, stop. Why, in fact, are these two cars not equal? We gave them the same properties, but the result of the comparison is false. The answer is simple. The operator ==compares not the properties of objects, but links. 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 with comparing people. 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 especially not the same person. Equals and string comparison - 2The operator applies approximately the same logic ==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’s logical that the result was the same (after all, we didn’t change anything), but now we’re not happy with it! Indeed, in real life, DNA analysis is a one hundred percent guarantee that we are facing twins. But our program and operator ==tell us otherwise. How can we change this behavior and make sure that if the DNA tests match, the program will produce 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, Objectthe most important class in Java, from which all other classes are derived. However, equals() 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 is this method needed then? :/ It's simple. The fact is that now we used this method as it is implemented in the class itself Object. And if we go into the class code Objectand look at how this method is implemented in it and what it does, we will see:
public boolean equals(Object obj) {
   return (this == obj);
}
This is the reason why the behavior of our program has not changed! Inside the class's equals() method Objectlies 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! Now we are not satisfied that the check man1.equals(man2)essentially does the same thing as 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
A completely different result! By writing our own equals() method instead of the standard one, we 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 necessary object comparison logic. We have touched on the comparison of objects only in general terms. We will still have a separate large lecture on this topic ahead (you can read it quickly now, if you are interested).

String compare in Java - String comparison

Why do we treat string comparisons separately from everything else? Well, in fact, lines in programming are a whole different story. Firstly, if you take all the Java programs written by mankind, about 25% of the objects in them are made up of them. Therefore, this topic is very important. Secondly, the process of comparing strings is really quite different from other objects. Let's look at a simple example:
public class Main {

   public static void main(String[] args) {

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

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

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush 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 ==actually compares addresses in memory. This rule always works and there is no need to doubt it. This means that 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 memory area for storing strings - the string pool ( String pool) Equals and string comparison - 3The string pool is an area for storing all the string values ​​that you create in your program. What was it created for? As mentioned earlier, strings take up a huge part of all objects. In any large program, a lot of lines are created. In order to save memory, this is what is needed String 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 whether there is a line with such 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 this string is stored. Therefore, when we wrote in the program
String s1 = "JavaRush is the best site to learn Java!";
String s2 = "JavaRush 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 didn’t this example work for us earlier?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush 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 is with the help of the operator new, and the second is without it. This is precisely the reason. The new operator, when creating an object, forcibly allocates a new area in memory for it . And the line created with new, does not end up in String Pool: it becomes a separate object, even if its text is exactly the same as the same line from String Pool'a. That is, if we write the following code:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       String s3 = new String("JavaRush is the best site to learn Java!");
   }
}
In memory it will look like this: Equals and string comparison - 4And every 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 seem to have sorted out the operator ==, but what about our new friend - the equals() method?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush 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, nevertheless, the equals() method says that they are equal. Why? Remember, above we said that the equals() method can be overridden in your class so that it compares objects the way you need? That's what they did with the class String. It has an overridden equals() method. And it compares not links, but rather the sequence of characters in strings. And if the text in the strings is the same, it does not 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 in a case-insensitive manner. In a normal situation, if you write one of the lines, for example, in caps, the result of the comparison will be false:
public class Main {

   public static void main(String[] args) {

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

false
For this case, the class Stringhas a method equalsIgnoreCase(). If the main thing in your comparison is the sequence of specific characters, and not their case, you can use it. For example, this will 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 a string, it:
  • Looks to see if there is a string with this text in the string pool
  • If there is, returns a link to it in the pool
  • If not, it places a line with this text in the string pool and returns a link to it.
By applying the method intern()to the string reference that was created via 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 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush 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()checked whether there was a line with the text "JavaRush - the best site for learning Java!" in the string pool. Of course it's there: we created it when we wrote
String s1 = "JavaRush is the best site to learn Java!";
It was checked that the reference s1and the reference returned by the method s2.intern()point to the same area in memory, and, of course, they do :) To summarize, 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 references, memory areas, and so on. The equals() method does exactly what you need. Here are some links for you to study on your own:
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION