Comparing objects

Available

1. Comparing objects in Java

In Java, objects can be compared both by reference and by value.

Comparing references

If two variables point to the same object in memory, then the references stored in these variables are equal. If you compare these variables using the equality operator (==), you get true, and that result makes sense. Everything is simple here.

Code Console output
Integer a = 5;
Integer b = a;
System.out.println(a == b);


true

Comparing by value

But you can often encounter situations where two variables refer to two distinct objects that are identical. For example, two different strings objects that contain the same text.

To determine whether different objects are identical, use the equals() method. For example:

Code Console output
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);
System.out.println(a.equals(b));


false
true

The equals method is not limited to the String class. Every class has it.

Even classes that you write on your own, and here's why.


11
Task
New Java Syntax,  level 11lesson 5
Locked
Period and comma
Periods and commas are important for more than just punctuation in ordinary text. Fix mistakes in the code, so that the program compiles and works correctly.

2. Object class

All classes in Java inherit the Object class. Java's creators came up with this approach.

And if a class inherits the Object class, then it gains all the methods of the Object class. And this is a major consequence of inheritance.

In other words, every class has the methods of the Object class, even if their code does not mention them.

These inherited methods include methods related to object comparison. These are the equals() and hashCode() methods.

Code In reality, here's what we'll have:
class Person
{
   String name;
   int age;
}
class Person extends Object
{
   String name;
   int age;

   public boolean equals(Object obj)
   {
      return this == obj;
   }

   public int hashCode()
   {
      return address_of_object_in_memory; // This is the default implementation, but there may be a different implementation
   }
}

In the example above, we created a simple Person class with name and age parameters, but not a single method. But because all classes inherit the Object class, the Person class automatically has two methods:

Method Description
boolean equals(Object obj)
Compares the current object and the passed object
int hashCode()
Returns the hashcode of the current object

It turns out that absolutely every object has the equals method, and objects of different types can be compared with each other. Such code will compile and work perfectly.

Code Console output
Integer a = 5;
String s = "Hello";
System.out.println(a.equals(s));
System.out.println(s.equals(a));


false
false
Object a = new Integer(5);
Object b = new Integer(5);
System.out.println(a.equals(b)) ;


true

3. equals() method

The equals() method, inherited from the Object class, implements the simplest algorithm for comparing the current object with passed objects: it just compares references to the objects.

You get the same result if you just compare Person variables instead of calling the equals() method. Example:

Code Console output
Person a = new Person();
a.name = "Steve";

Person b = new Person();
b.name = "Steve";

System.out.println(a == b);
System.out.println(a.equals(b));






false
false

When the equals method is called on a, it simply compares the reference stored in the a variable with the reference stored in the b variable.

However, comparison works differently for the String class. Why?

Because the folks who created the String class wrote their own implementation of the equals() method.

Implementation of the equals() method

Now let's write our own implementation of the equals method in the Person class. We'll consider 4 main cases.

Important:
Regardless of which class overrides the equals method, it always takes an Object object as an argument

Scenario 1: the same object on which the equals method is called is also passed to the equals method. If the references of the current object and the passed object are equal, the method must return true. An object is equal to itself.

In code it will look like this:

Code Description
public boolean equals(Object obj)
{
   if (this == obj)
    return true;

   // The rest of the code of the equals method
}


Compare references

Scenario 2: null is passed to the equals method — we have nothing to compare to. The object on which the equals method is called is definitely not null, so we need to return false in this case.

In code it will look like this:

Code Description
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   // The rest of the code of the equals method
}


Compare references


Is the passed object null?

Scenario 3: a reference to an object that is not a Person is passed to the equals method. Is the Person object equal to the non-Person object? That is a question for the developer of the Person class to decide however he or she wants.

But usually objects must be of the same class to be considered equal. Therefore, if something other than an object of the Person class is passed to our equals method, then we will always return false. How can you check the type of an object? That's right — by using the instanceof operator.

Here's what our new code looks like:

Code Description
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   if (!(obj instanceof Person))
      return false;

   // The rest of the code of the equals method
}


Compare references


Is the passed object null?


If the passed object is not a Person

4. Comparing two Person objects

What did we end up with? If we have reached the end of the method, then we have a Person object reference that is not null. So we convert it to a Person and compare the relevant internal data of both objects. And that is our fourth scenario.

Code Description
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   if (!(obj instanceof Person))
      return false;

   Person person = (Person) obj;

   // The rest of the code of the equals method
}


Compare references


Is the passed object null?


If the passed object is not a Person


Typecasting

And how do you compare two Person objects? They are equal if they have the same name (name) and age (age). The final code will look like this:

Code Description
public boolean equals(Object obj)
{
   if (this == obj)
      return true;

   if (obj == null)
      return false;

   if (!(obj instanceof Person))
      return false;

   Person person = (Person) obj;

   return this.name == person.name && this.age == person.age;
}


Compare references


Is the passed object null?


If the passed object is not a Person


Typecasting

But that's not all.

First, the name field is a String, so you need to compare the name field by calling the equals method.

this.name.equals(person.name)

Second, the name field may be null: in that case, you cannot call equals on it. You need an additional check for null:

this.name != null && this.name.equals(person.name)

That said, if the name field is null in both Person objects, then the names are still equal.

The code for the fourth scenario might look like this:

Person person = (Person) obj;

if (this.age != person.age)
   return false;

if (this.name == null)
   return person.name == null;

return this.name.equals(person.name);


If the ages are not equal,
immediately return false

If this.name is equal to null, there is no point in comparing using the equals method. Here either the second name field is equal to null, or it is not.

Compare the two name fields using the equals method.

11
Task
New Java Syntax,  level 11lesson 5
Locked
Oh, these damnable quotation marks
The code already has quotation marks, but as it turns out, there are not enough of them. Fix mistakes in the code, so that the program compiles and works correctly.

5. hashCode() method

In addition to the equals method, which is intended to perform a detailed comparison of all the fields of both objects, there is another method that can be used for an imprecise but very quick comparison: hashCode().

Imagine you are alphabetically sorting a list of thousands of words, and you need to repeatedly compare pairs of words. And the words are long, consisting of lots of letters. Generally speaking, such a comparison would take a very long time.

But it can be accelerated. Suppose we have words that begin with different letters — it's immediately clear that they are different. But if they begin with the same letters, then we can't yet say what the result will be: the words may turn out to be equal or different.

The hashCode() method works using a similar principle. If you call it on an object, it returns some number — analogous to the first letter in a word. This number has the following properties:

  • Identical objects always have the same hashcode
  • Different objects can have the same hashcode, or their hashcodes can be different
  • If objects have different hashcodes, then the objects are definitely different

To make this even more clear, let's reframe these properties in terms of words:

  • Identical words always have the same first letters.
  • Different words can have the same first letters, or their first letters can be different
  • If words have different first letters, then the words are definitely different

The last property is used to accelerate comparison of objects:

First, the hashcodes of the two objects are calculated. If these hashcodes are different, then the objects are definitely different, and there is no need to compare them further.

But if the hashcodes are the same, then we still have to compare the objects using the equals method.


11
Task
New Java Syntax,  level 11lesson 5
Locked
Con, Cat, Enation
"Con", "cat", "enation". How would you merge these three strings? Do you remember how to concatenate Strings in Java? Fix mistakes in the code, so that the program compiles and works correctly.

6. Contracts in code

The behavior described above must be implemented by all classes in Java. During compilation, there is no way to check whether objects are compared correctly.

Java programmers have a universal agreement that if they write their own implementation of the equals() method and thereby override the standard implementation (in the Object class), they must also write their own implementation of the hashCode() method in such a way that the aforementioned rules are satisfied.

This arrangement is called a contract.

If you implement only the equals() or only the hashCode() method in your class, then you are in gross violation of the contract (you've broken the agreement). Don't do this.

If other programmers use your code, it may not work correctly. What's more, you will use code that relies on adherence to the above contracts.

Important!

When searching for an element, all Java collections first compare the hashcodes of objects, and only then perform a comparison using the equals method.

That means that if you give your own class an equals method but you do not write your own hashCode() method or you implement it incorrectly, then collections may not work correctly with your objects.

For example, you might add an object to a list and then search for it using the contains() method, but the collection might not find your object.

11
Task
New Java Syntax,  level 11lesson 5
Locked
Keeping track of parentheses
It seems we have an extra parenthesis? Or is one missing? Deal with the problem.
11
Task
New Java Syntax,  level 11lesson 5
Locked
And parentheses once again
It seems that once again the problem is with the parentheses. But with different ones this time. Fix mistakes in the code, so that the program compiles and works correctly.
11
Task
New Java Syntax,  level 11lesson 5
Locked
The long-suffering main method
Make one fix in the code to get the program to run.
11
Task
New Java Syntax,  level 11lesson 5
Locked
Correct class
Fix mistakes in the code, so that the program compiles and works correctly.
11
Task
New Java Syntax,  level 11lesson 5
Locked
Need a package?
Fix a mistake in the code, so that the program compiles and works correctly.
11
Task
New Java Syntax,  level 11lesson 5
Locked
Imported code
Fix a mistake in the code, so that the program compiles and works correctly.
Comments (18)
  • Popular
  • New
  • Old
You must be signed in to leave a comment
Knightrider
Level 11 , London, United Kingdom
12 January, 10:43
for the two iphones one this should help as they are useless - if(this == obj){ return true; } if(obj == null){ return false; } if(!(obj instanceof Iphone)){ return false; } Iphone phone = (Iphone) obj; return Objects.equals(this.model, phone.model) && Objects.equals(this.color, phone.color) && this.price == phone.price;
Evgeniia Shabaeva
Level 32 , Budapest, Hungary
29 April 2024, 13:43
When I was doing the task in the 4th section, I was initially scared by the task to override a method (as we had not yet studied this whole overriding thing). But then I just wrote my own method called public boolean equals(Object obj) (almost the same as in the text of the lesson, just with different names in it) under the comment //write your code here, and it worked perfectly well. So, the good news is we do not need @Override stuff right now (though I hope we'll cover it soon).
Pekotski
Level 16 , Zurich, Switzerland
2 December 2023, 21:05
Two Iphones - beyond my understanding why is this allowed at this stage? Inheritance or overwriting was not covered yet. This course is becoming a joke.
Tomasz Enyeart
Level 16 , United States
9 February 2024, 18:56
i dpnt want to say it but this cousre kinda sucks, and they dont care, half the tasks have requirement like "follow the description " and then they do this
Campbell, Jackson
Level 12 , Corona, USA
6 November 2023, 22:51
idk how I did it right ngl
Harshit Garg
Level 23 , Chandigarh, India
Expert
20 August 2023, 02:18
class Person extends Object
{
   String name;
   int age;

   public boolean equals(Object obj)
   {
      return this == obj;
   }

   public int hashCode()
   {
      return address_of_object_in_memory; // This is the default implementation, but there may be a different implementation
   }
}
what does "this== obj" do? what does @override do? what is hashcode -- what does "Objects.hash(model, year);" do?
Serhii Matviienko
Level 21 , Ukraine, Ukraine
Expert
20 August 2023, 17:54
@Override annotation informs the compiler that the element is meant to override an element declared in a superclass. It's not always required, but helps to prevent errors. Since every object in Java extends Object class, we usually override it's equals(Object obj) and hashCode() methods. And if we override parent's method and use @Override and then decide to change method's signature (like add some paramether to method or change it's name), compiler will generate an error, code won't compile.
Parsa
Level 68 , Bangalore, India
Expert
19 November 2023, 15:33
this == obj compares their references. If both this and obj point to the same object, then they're both equal. Here's a photo I made. I hope it helps: And regarding the hashCode method, it returns an integer which is the hash code. The hash code is internally calculated based on the objects given, here, model and year. If model and year are the same, the hash code will also be the same, so we can use that for comparison.
curi0usmind System Administrator Expert
10 August 2023, 16:57
"That said, if the name field is null in both Person objects, then the names are still equal." How? return this.name != null && this.name.equals(that.name) && this.age == that.age; If both are null then the condition this.name != null makes the whole return statement return false. And when one of them is null then this.name.equals(that.name) will return false. So it's not possible for the names to still be equal!
Zac Fullstack Startup Lawyer
3 June 2023, 12:01
The problem with the answers below saying things like, "just search the internet!" Is that this course never suggests you're supposed to. The course, so far, has clearly implied that it is teaching you the skills and knowledge you need to answer the questions. It's totally great and normal if we need to jump on google or stack overflow to get answers -- that itself is a core skill we all need! But if the course is suggesting that it has equipped us to solve an exercise when that isn't true, then the course should at minimum say something like, "We haven't covered Overriding yet -- do a google search to see how this is implemented" or similar.
Abe unemployed
20 February 2023, 19:50
I have no clue how to even understand the solution for the 'two iphones' task: what is the 'getClass()' doing? for instance...but really I wish there was a line by line explanation describing what it is doing...
Gandhar K
Level 37 , India
Expert
3 October 2023, 11:22
getClass() is the method of object class. Its used to get the class of that object. Basically the line checks if objects in comparison belong to same classes. Objects of different classes cannot be considered equal.
Dillon Morgan
Level 21 , London, United Kingdom
13 February 2023, 23:05
This lesson is one of the more difficult to follow. I feel the use of the Integer object for the examples earlier on in the lesson can make it difficult to see the difference between different implementations of the inherited "equals" methods. Especially when the String class is identified as having a special implementation but Integer class is not. Note the conflicting messages at the end of Section 2 and beginning of Section 3.
Patryk Kotański
Level 24 , Poland
23 December 2022, 15:21
How am I supposed to write my own implementation of a function that I haven't used regular one before? This task teaches nothing.
17 January 2023, 18:00
Well... it teaches you to search the web for the answer 😉 The truth is out there.
Evan
Level 33 , United States of America, USA
21 January 2023, 19:16
A quick article search can help fill in the blanks! https://codegym.cc/groups/posts/264-equals-and-hashcode-methods-best-practices
Rene
Level 28 , Netherlands
8 February 2024, 22:32
Yes.. don't be a user. Become a developer. Solving issues becomes your drive! And to add something useful: use an IDE (like IntelliJ). It gives you a lot of information on classes and methods available while you are writing your code.
Tomasz Enyeart
Level 16 , United States
9 February 2024, 19:01
Rene but people pay for this cousre and they need to provided people what they are paying for. there are countless resources on the internet but when you pay for a service and its not provided it can frustrating.