Pavel Ryzhov
Pavel Ryzhov

Reputation: 5162

Implementation equals() method design pattern

Is there any design pattern (or idiom) that helps to implement equals() method in Java?

That task is'n so hard but in most cases it's about the same... That's why I guess that there is a pattern but I didn't find it.

UPDATE

I chose the method: generate equals() method in Eclipse but... I found a good way (in AbstractList) to make that generated code better:

if (!(attributes ==null ? other.attributes==null : attributes.equals(other.attributes))) 
    return false; 

instead of generated:

if (attributes == null) {
        if (other.attributes != null)
        return false;
    } else if (!attributes.equals(other.attributes))
        return false;

Upvotes: 1

Views: 2335

Answers (7)

chaotic3quilibrium
chaotic3quilibrium

Reputation: 5924

Regarding adding equals and hashCode for JPA/Hibernate entities, please see this StackOverflow Answer.


The code pattern recommended below depends upon the new instanceof pattern matching functionality released for preview in Java 14 (2020/Mar/17), and then fully released in Java 16 (2021/Mar/16).


I really dislike seeing explicit uses of true and false, especially when they fall directly out of evaluated logic.

So, I am not at all fond of the default code pattern generated by my IDE (IntelliJ) when overriding and implementing equals() in my classes.

It looks like this:

//Legacy laden pattern produced by IntelliJ code generator
public boolean equals(Object o) {
  if (this == o) {
    return true;
  }
  if (o == null || getClass() != o.getClass()) {
    return false;
  }
  EqualsExampleClass that = (EqualsExampleClass) o;
  return Objects.equals(stringy, that.stringy)
      && (inty == that.inty)
      && Objects.equals(bigIntegery, that.bigIntegery)
      && (booleany == that.booleany);
}

Encouraged by Oracle JEP 394 for the instanceof pattern matching, I've refactored the above code to look like this:

//Modern flowing fluent style
@Override
public boolean equals(Object o) {
  return (this == o) ||
      ((o instanceof EqualsExampleClass that)
          && (this.getClass() == that.getClass())
          && Objects.equals(this.stringy, that.stringy)
          && (this.inty == that.inty)
          && Objects.equals(this.bigInt, that.bigInt)
          && (this.booleany == that.booleany));
}

Per line execution details:

  1. (this == o) - checks for literally the same instance
  2. (o instanceof EqualsExampleClass that) - checks to ensure o is not null, o is an instance of this class (or a descendant), and if so, assigns o to the narrowed type variable that
  3. (this.getClass() == that.getClass()) - requires the equals comparison is between two instances of the same class (i.e., that is not an instance of a descendant class), and can be removed if, and only if, this class is marked final
  4. Objects.equals(this.stringy, that.stringy) - is using Objects.equals() on references (not primitives) to ensure that if either side returns a null, the comparison is successfully made without throwing a NullPointerException

This code implementation pattern is considerably easier to functional flow read, analyze, reason about, and debug, during a refactoring pass.

Upvotes: 1

sakthisundar
sakthisundar

Reputation: 3288

Look at what Java Language Specification got to say.

equals method just defines the notion of object equality

Apart from that there is no design pattern involved in designing this method. The truth is that equals method is already designed by Java language designers and you can only make use of the design. If you are not confident of how to write your own equals method, consider taking the help of IDE's like eclipse which does the job for you.

Upvotes: 1

dvsander
dvsander

Reputation: 105

I always use following code:

if (null == obj) return false;
if (this == obj) return true;
if (!(object instanceof MyClass)) return false;
MyClass that = (MyClass) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(this.businessKey, that.businessKey);
return eb.isEquals();

...

I never use technical keys like sequences or pk's, always business fields. Therefore I don't believe this can be made generic but must be made specific to any given Class.

Upvotes: 3

Nandkumar Tekale
Nandkumar Tekale

Reputation: 16158

Generally to implement equals() method, what I do is : I generate those from Eclipse as Eclipse can generate hashCode, toString and equals() methods very well.

Upvotes: 4

Yogendra Singh
Yogendra Singh

Reputation: 34367

Not sure about your expectation. equals() is meant for defining your criteria of comparing two different objects of your class for equality.

In general, you compare each attribute one by one but its very much possible and supported that you do the comparison using fewer selected attributes only.

Upvotes: -1

Andreas Fester
Andreas Fester

Reputation: 36650

Maybe this helps: Implementing equals. Especially be aware of the close relationship betweeen hashcode() and equals(). Other than that, I suppose the concrete implementation of equals() really depends on your class design, means when do you treat two objects equal.

Upvotes: 1

Anders R. Bystrup
Anders R. Bystrup

Reputation: 16060

It is pretty much up to yourself to decide when two object are "the same" in a certain sense... Should they be equal when they contain the same data (perfectly valid usecase) or more strictly when they are the same physical object in memory (also valid) or just the same row in a DB when compared in a clustered environment?

Just remember to also override .hashCode() or you're in for a world of hurt :-)

(Also, good article suggestions from @Andreas and @flash.)

Cheers,

Upvotes: 1

Related Questions