Is There a Java Utility to Do a Deep Comparison of Two Objects

Java Deep Comparison Returns False when Comparing a Deep Copy

One of the common misconceptions in Java is the use of == vs .equals(). When you use == to compare two objects in Java, internally it's comparing its memory address. == does not actually call .equals().

In this case, you have two distinct orange objects, so the comparison will always return false.

If you use a.equals(b), then it will actually invoke your equals method which you implemented.

As @Andreas pointed out in the comments, there's another issue. Calling super.equals(obj) in Fruit will call the superclass implementation of equals, and the superclass of Fruit is Object. Object.equals() behaves the same as == (i.e. also checking for reference equality). Overriding .equals() is not trivial, so it can often be nice to have the IDE generate it for you.

In contrast with a language like C++, Java does not have operator overloading. This means that you can't define a different implementation for ==. This is why it's best practice to always call .equals() when comparing any non-primitive types (unless you're explicitly checking reference equality, which is rare).

Check if two objects are completely equal in Java

You have a few options for automating Equals & Hashcode (option #3 BLEW MY MIND!):

  1. Your IDE. I would not recommend it for most objects as they can slowly drift out of date with the actual class definition. They also look ugly and pollute your codebase with boilerplate code.
  2. Apache Commons has a bunch of stuff for making this easier, including a reflective version so no risk of drifting out of date with the class definition. It is better than #1 unless you require a speedy equals/hashcode, but still too much boilerplate for my liking.
  3. Project Lombok and annotation processing. Whack an EqualsAndHashCode annotation on ya class and be done with it. I recommend using Project Lombok. It adds a touch of magic into the build (but not much) and so requires a plugin for your IDE to behave nicely but they are a small price to pay for no boilerplate code. Lombok is an annotation processor that run at compile time so you have no runtime performance hit.
  4. Using a different language that supports it out the box, but also targets the JVM. Groovy uses an annotation and Kotlin supports data classes. Unless your existing code can quickly be converted, I would avoid this.
  5. Google's Auto has an AutoValue. Like Project Lombok this is an annotation processor, however has less magic at the expense of little more boilerplate (thanks to Louis Wasserman)

Deep reflective compare equals

From the answer to this question https://stackoverflow.com/a/1449051/116509 and from some preliminary testing, it looks like Unitils' ReflectionAssert.assertReflectionEquals does what you're expecting. (Edit: but may be abandoned, so you could try AssertJ https://assertj.github.io/doc/#assertj-core-recursive-comparison)

2021 edit: EqualsBuilder now has a testRecursive option. However the unit test libraries mentioned will give you a better failure message to help debug, so depending on context, they're still the best option.

Compare two objects excluding some fields - Java

The quickest way without writing any code is Lombok

Lombok is one of the most used libraries in java and it takes a lot of Boilerplate code off your projects. If you need to read more on what it can and does, go here.

The way to implement what you need is pretty straightforward:

// Generate the equals and HashCode functions and Include only the fields that I annotate with Include
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Getter // Generate getters for each field
@Setter // Generate setters for each field
public class Class1
{

@EqualsAndHashCode.Include // Include this field
private Long identity;

private String testStr1; // This field is not annotated with Include so it will not be included in the functions.

// ... any other fields
}

Lombok can do a lot more than this. For more information on @EqualsAndHashCode refer to this.

You can always use @EqualsAndHashCode.Exclude for a quicker solution to your use case:

@EqualsAndHashCode
@Getter // Generate getters for each field
@Setter // Generate setters for each field
public final class Class1 {
private String a;
private String b;
private String c;
:
:
:

private String z;

@EqualsAndHashCode.Exclude
private Date createdAt;
@EqualsAndHashCode.Exclude
private Date updatedAt;
}

What is the fastest and efficient way to check Deep Equal for two java objects?

Override equals() or have a *helper method (bad option!) and do it in 5 steps :

1. Check for *not null*.
2. Check for same *type*.
3. Check for *size of byte[]*.
4. Check for `==` (*reference equality* of byte[])
5. Start comparing byte values


Related Topics



Leave a reply



Submit