{"id":3241,"date":"2024-04-30T15:30:50","date_gmt":"2024-04-30T15:30:50","guid":{"rendered":"https:\/\/msgprogramator.sk\/?p=3241"},"modified":"2025-07-07T10:57:25","modified_gmt":"2025-07-07T10:57:25","slug":"java-objects-comparison","status":"publish","type":"post","link":"https:\/\/msgprogramator.sk\/en\/java-objects-comparison\/","title":{"rendered":"How to compare Java objects correctly"},"content":{"rendered":"<p>In an object-oriented programming language like Java, comparing objects to each other or to primitive types is a fundamental yet often misunderstood task. While experienced developers handle this routinely, novice programmers frequently struggle with when to use the equality operators (<strong>==<\/strong> and <strong>!=<\/strong>) versus methods like <strong>equals()<\/strong> or <strong>compareTo()<\/strong>. <\/p>\n<p>Object comparison is the process of checking whether or not two objects are the same, based on data or references. In Java, objects are created from classes, and each object has its own set of data and defined behaviour. However, we can also compare whether the objects occur at the same location in memory, and if so, they are not two objects, but one and the same.  <\/p>\n<p>In this article, we will use practical examples to show how to correctly compare objects in Java, either based on the data in the objects or their references. You will also learn how the equals() method is implemented and works, and we will also mention the importance of implementing the <strong>hashCode()<\/strong> method to efficiently compare objects using the hash algorithm. <\/p>\n<h2>Comparing objects with primitive types<\/h2>\n<p>In Java, primitive types such as <strong>int<\/strong>, <strong>double<\/strong>, <strong>boolean<\/strong>, etc. are not objects, but basic data types. When comparing objects with primitive types, Java automatically converts the corresponding <em>wrapper<\/em> object of a class to its primitive type using the extension primitive conversion (<a href=\"https:\/\/docs.oracle.com\/javase\/specs\/jls\/se7\/html\/jls-5.html#jls-5.1.2\" target=\"_blank\" rel=\"nofollow noopener\">\u00a75.1.2<\/a>). The following rules are specified:   <\/p>\n<ul>\n<li>f one operand is double, the other converts to double.<\/li>\n<li>Otherwise, if one is float, the other converts to float.<\/li>\n<li>Otherwise, if one is long, the other converts to long.<\/li>\n<li>Otherwise, both convert to int.<\/li>\n<\/ul>\n<p><u>Example:<\/u><\/p>\n<pre><code class=\"language-java\" data-line=\"\">Integer I = new Integer(5);\nint i = 5;\n\nSystem.out.println(I == i);\n\/\/ =&gt; true\n\nSystem.out.println(I.equals(i));\n\/\/ =&gt; true\n<\/code><\/pre>\n<p>If we compare an object with its primitive type, either using the <strong>==<\/strong> operator or the equals method, it is equivalent, and if the values are the same, the result is a boolean <strong>true<\/strong>.<\/p>\n<h2>Comparing objects by reference<\/h2>\n<p>The identity of a variable (also called reference equality) is defined by the reference it has. If two variables have the same reference, they are identical. This is controlled by the == operator. It is important to remember that the == operator in Java is used to compare the references of two objects, not their contents. So it checks whether both references point to exactly the same object in memory (or its address).  <\/p>\n<p><u>Example:<\/u><\/p>\n<pre><code class=\"language-java\" data-line=\"\">String s1 = new String(&quot;Java&quot;);\nString s2 = new String(&quot;Java&quot;);\nSystem.out.println(s1 == s2);\n\/\/ =&gt; false\n<\/code><\/pre>\n<p>In this example, both strings have the same text, but since we are comparing references (memory addresses of two different instances), the result is understandably a boolean value of <strong>false<\/strong>.<\/p>\n<p><u>Example:<\/u><\/p>\n<pre><code class=\"language-java\" data-line=\"\">String s1 = new String(&quot;Java&quot;);\nString s2 = s1;\nSystem.out.println(s1 == s2);\n\/\/ =&gt; true\n<\/code><\/pre>\n<p>However, if instead of creating an instance in the second string, we copy the reference to the first string when comparing references, the result is true.<\/p>\n<h2>Comparing objects by value<\/h2>\n<p>The equality of a variable is defined by the value it refers to. If two variables refer to the same value, they are equal. In Java, this is checked using the equals() method. It is part of the Object class, which is the parent class of all Java classes. This means that we can use equals in Java to compare the data contents of any two objects.    <\/p>\n<p><u>Example:<\/u><\/p>\n<pre><code class=\"language-java\" data-line=\"\">String s1 = new String(&quot;Java&quot;);\nString s2 = new String(&quot;Java&quot;);\nSystem.out.println(s1.equals(s2));\n\/\/ =&gt; true\n<\/code><\/pre>\n<p>The example shows how to compare 2 different instances of the String type with the same text. The result of the equals() call returns the boolean value true. If we had a copied reference to the same object in the previous example, the result of comparing the values of the same object would also be true.  <\/p>\n<p><u>Example:<\/u><\/p>\n<pre><code class=\"language-java\" data-line=\"\">String s1 = new String(&quot;Java&quot;);\nString s2 = s1;\nSystem.out.println(s1.equals(s2));\n\/\/ =&gt; true\n<\/code><\/pre>\n<p>So far we have used simple objects in the examples that the Java authors have provided in the libraries. Now let&#8217;s try to create our own object and have a look at the equals() method. <\/p>\n<p><u>Example:<\/u><\/p>\n<p>Shape class<\/p>\n<pre><code class=\"language-java\" data-line=\"\">package pack;\n\npublic class Shape {\n    String colour;\n\n    public Shape(String colour) {\n        this.colour = colour;\n    }\n\n    public String getColour() {\n        return colour;\n    }\n\n    public void setColour(String colour) {\n        this.colour = colour;\n    }\n}\n<\/code><\/pre>\n<p>Circle class<\/p>\n<pre><code class=\"language-java\" data-line=\"\">package pack;\n\npublic class Circle extends Shape {\n    double radius;\n\n    public Circle (String colour, double radius) {\n        super(colour);\n        this.radius = radius;\n    }\n\n    public double getRadius() {\n        return radius;\n    }\n\n    public void setRadius(double radius) {\n        this.radius = radius;\n    }\n}\n<\/code><\/pre>\n<p>We have created a Circle class that inherits from the parent Shape class. We will now create two instances with the same data and compare their references and values using the equals method. <\/p>\n<pre><code class=\"language-java\" data-line=\"\">Circle c1 = new Circle(&quot;green&quot;, 1);\nCircle c2 = new Circle(&quot;green&quot;, 1);\n\nSystem.out.println(c1 != c2);\n\/\/ =&gt; true\n\nSystem.out.println(c1.equals(c2));\n\/\/ =&gt; false\n<\/code><\/pre>\n<p>The fact that the references to the two different instances are different is what we expected. The surprise, however, may be that even though both objects have the same attribute values, the equals method returns false, meaning that the values of the two objects are different. This is because the default equals implementation in the Object class, which every object inherits, compares the memory addresses of objects, so it works just like the == operator. So we need to rewrite this method to define what equality means for our objects. But first we need to know the rules that the Equals method follows.    <\/p>\n<h3>Equals() method rules<\/h3>\n<p>Suppose we have defined x, y, z references. Then a correctly implemented equals method should have the following properties: <u>Reflexivity:<\/u> for any non-zero reference x, x.equals(x) should return true. <u>Symmetry:<\/u> for all non-zero references x and y, x.equals(y) should return true if and only if y.equals(x) returns true. <u>Transitivity:<\/u> for all non-zero references x, y and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. <u>Consistency:<\/u> for any non-zero references x and y, multiple invocations of x.equals(y) will consistently return the same true or false values in sequence, provided that no information used in the equals comparison of the objects is changed. For any non-null reference x, x.equals(null) should return false. <\/p>\n<h2>Correct implementation of equals()<\/h2>\n<p>Now that we know the rules for equals, let&#8217;s implement our own version of equals for the Circle class.<\/p>\n<pre><code class=\"language-java\" data-line=\"\">@Override\npublic boolean equals(Object o) {\n    \/\/ self check\n    if (this == o) return true;\n\n    \/\/ Null check\n    if (o == null) return false;\n\n    \/\/ Type check and cast\n    if (getClass() != o.getClass())\n        return false;\n    \n    Circle circle = (Circle) o;\n\n    \/\/ Field comparison\n    return Objects.equals(radius,  circle.radius)\n            &amp;&amp; Objects.equals(colour, circle.colour);\n}\n<\/code><\/pre>\n<p>We&#8217;ll check that both instances contain the same values and that the equals method works correctly and returns true.<\/p>\n<pre><code class=\"language-java\" data-line=\"\">Circle c1 = new Circle(&quot;green&quot;, 1);\nCircle c2 = new Circle(&quot;green&quot;, 1);\nSystem.out.println(c1.equals(c2));\n\/\/ =&gt; true\n<\/code><\/pre>\n<p>In our implementation of equals, we first check that we&#8217;re comparing the object to itself, and if we are, the result is true. Then we check that the reference to the second object to which we are comparing the first object is valid (i.e. non-zero), and if it is not, we return false. No instance should be null, and this line ensures that we don&#8217;t get a NullPointerException when accessing attributes later. Before comparing the attributes, we test that the two objects being compared belong to the same class. This also ensures that even if the Circle class is separated from the Shape class, comparing these classes will always return false.<\/p>\n<h2>The hashCode() method<\/h2>\n<p>A common practice in Java is that when we override the original implementation of equals(), we should also override the hashCode() method, since both methods work together, especially when dealing with collections of objects. The connection between the two methods is that if the equals method determines that the two objects are the same, then they should also compute the same hash code. Without a correct implementation of the hash code, the use of collections that depend on it, such as <em>HashSet <\/em> and <em>HashMap<\/em>, will not work correctly. Let&#8217;s take a look at our Circle class to see how we should correctly overload the hashCode() method.<\/p>\n<pre><code class=\"language-java\" data-line=\"\">@Override\npublic int hashCode() {\n    return Objects.hash(radius, colour);\n}\n<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>In Java, comparing two objects is not as simple as comparing two primitive data types. It requires a deeper understanding of the structure of objects and how they are stored in memory. The equals() method is the primary method for comparing two objects in Java. When we override the equals() method, we must also override the hashcode() method to ensure that two identical objects have the same hash code. By using the equals() and hashcode() methods, we can effectively compare two objects based on their internal state rather than their location in memory.    <\/p>\n<p>If you&#8217;re a <a href=\"https:\/\/msg-life.sk\/en\/jobs\/java-programmer-senior\/\">Java developer<\/a> looking for a job, check out our <a href=\"https:\/\/msg-life.sk\/en\/benefits\/\">employee benefits<\/a> and respond to our <a href=\"https:\/\/msg-life.sk\/en\/jobs\/\">job offers<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we will use practical examples to show how to correctly compare Java objects, either based on the data in the objects or their references.<\/p>\n","protected":false},"author":14,"featured_media":3229,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[57],"tags":[],"class_list":["post-3241","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts\/3241","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/comments?post=3241"}],"version-history":[{"count":5,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts\/3241\/revisions"}],"predecessor-version":[{"id":5330,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/posts\/3241\/revisions\/5330"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/media\/3229"}],"wp:attachment":[{"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/media?parent=3241"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/categories?post=3241"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msgprogramator.sk\/en\/wp-json\/wp\/v2\/tags?post=3241"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}