Wednesday, 31 May 2017

Tutorial 31: The equals() Method



The equals() method helps us to check whether two objects are equal. To show you the importance of the equals() method, I will first create a problem that the equals method is going to help us solve.

So, let’s imagine that we create a class called Bird. Then, let us give Bird two member variables: String name and int id. Then, we can give Bird a constructor that allows us to instantiate both the name and the id of Bird objects as we create them. Let us also give Bird a toString method.

public class Bird {
            private String name;
            private int id;
            public Bird (String name, int id) {
                        this.name = name;
                        this.id = id;
            }
            @Override
            public String toString() {
                        return “Person [id- ” + id + “, name- ” + name + “]”;
            }
}

Now, let’s create two Bird objects bird1 and bird2 and instantiate them in the main method:

public class Bird {
            private String name;
            private int id;
            public Bird (String name, int id) {
                        this.name = name;
                        this.id = id;
            }
            @Override
            public String toString() {
                        return “Bird [name- ” + name + “, id- ” + id + “]”;
            }
            public static void main (String[] args) {
                        Bird bird1 = new Bird (“Hawk”, 2);
                        Bird bird2 = new Bird (“Chicken”, 6);
}
}

Now, let us compare if the two objects are equals using the ==boolean operator:

public class Bird {
            private String name;
            private int id;
            public Bird (String name, int id) {
                        this.name = name;
                        this.id = id;
            }
            @Override
            public String toString() {
                        return “Bird [name- ” + name + “, id- ” + id + “]”;
            }
            public static void main (String[] args) {
                        Bird bird1 = new Bird (“Hawk”, 2);
                        Bird bird2 = new Bird (“Chicken”, 6);
                        System.out.println (bird1 == bird2);
}
}

Figure 1: Two objects of the class Bird are not the same
 
As you can see, Java says that bird1 and bird2 are not the same. Now let me point out something interesting about how the == operator works. If we are comparing native objects, such as objects of type int, float, short, byte, long, float or double, Java will return true if the two objects are equal.

When we, however, tell Java to compare two custom objects using the == operator, Java compares whether the two reference variables point to the same object. If they do, it returns true. If they don’t, it returns false. So, equating bird1 to bird2 or equating bird2 to bird1 will return true as shown below:

public class Bird {
            private String name;
            private int id;
            public Bird (String name, int id) {
                        this.name = name;
                        this.id = id;
            }
            @Override
            public String toString() {
                        return “Bird [name- ” + name + “, id- ” + id + “]”;
            }
            public static void main (String[] args) {
                        Bird bird1 = new Bird (“Hawk”, 2);
                        Bird bird2 = new Bird (“Chicken”, 6);
                        bird1 = bird2;
                        System.out.println (bird1 == bird2);
}
}


Figure 2: Making the reference variables point to the same object


In the above program, even if we gave bird1 and bird2 the same name and id, Java will still say that they are not equal. And this is, as I’ve said before, because of the fact that the two reference variables are referring to two completely different objects.

public class Bird {
            private String name;
            private int id;
            public Bird (String name, int id) {
                        this.name = name;
                        this.id = id;
            }
            @Override
            public String toString() {
                        return “Bird [name- ” + name + “, id- ” + id + “]”;
            }
            public static void main (String[] args) {
                        Bird bird1 = new Bird (“Hawk”, 2);
                        Bird bird2 = new Bird (“Hawk”, 2);
                        System.out.println (bird1 == bird2);
}
} 



Figure 3: Two objects with same id and name declared as not equal by Java


When we are comparing two objects, we usually have an idea of what equality between them actually means. For example, we can say that two vehicles are equal if they are the same make, the same year of manufacture, the same mileage, the same color, etc. They don’t have to literally be the same object. And this is where the equals() method comes into play.

The equals() method is a method that all objects inherit from the Object class. So we are now going to compare the two objects like this:



public class Bird {
            private String name;
            private int id;
            public Bird (String name, int id) {
                        this.name = name;
                        this.id = id;
            }
            @Override
            public String toString() {
                        return “Bird [name- ” + name + “, id- ” + id + “]”;
            }
            public static void main (String[] args) {
                        Bird bird1 = new Bird (“Hawk”, 2);
                        Bird bird2 = new Bird (“Hawk”, 2);
                        System.out.println (bird1.equals(bird2));
}
Figure 4: Using the .equals() method, which still says the objects with the same name and id are different


In the above program, Java will still return false even when we use the equals() method. This is because we haven’t yet told Java how we want the objects to be compared. So what we need to do is to override the equals method. The easiest way is to right click within the class file, if you are using Eclipse, go to Source and then select “Generate hashCode() and equals()”

Select the fields that you would like to compare for equality and click Ok. This is where you tell Java what fields to consider when determining whether two objects are equal. The following figure shows the generated equals() and hashCode() methods.

Now, with the equals() and hashCode() methods defined, if two objects have the same name and id, then Java will say that they are, indeed, equal and return true.


Figure 5: Implementing the hashCode() and equals() methods to make .equals() work correctly


With numeric types, you can just use the default equals() method. For example, if you create two objects of type Double, you can compare them like this:

Double number1 = 135.7;
Double number2 = 135.7;
System.out.println(number1.equals(number2));



Figure 6: Comparing two Double values using .equals(). .equals() is more reliable than the == operator


Java will return true if the two values are indeed equal. Remember that == checks whether or not two references point to the same object. So the safest way is always to use the equals() method, because it provides a sematic comparison of the two object rather than a memory based location comparison. 

Therefore, never compare non-primitive objects using the == operator. Instead, use the equals() method.

Now you might be wondering what the hashCode() method is for. A hash code is just a unique id that every object has. It is the value that is returned when we call the hashCode() method on an object. The hash code is important when putting objects in a set or a hashmap and we are going to look at this in the course on the collections framework.

Keep the .equals() method in mind because it is a very common interview and exam question. 

If you have any questions or comments, please feel free to drop them in the comments section below and I will address them.

Until next time, take care.   


No comments:

Post a Comment