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;
}
Answer from Renis1235 on Stack OverflowThe 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;
}
If overriding Object::equals and Object::hashCode is not an option, we can use the Comparator API to construct a corresponding comparator:
final Comparator<Class1> comp = Comparator.comparing(Class1::getA)
.thenComparing(Class1::getB)
.thenComparing(Class1::getC)
.
.
.
.thenComparing(Class1::getZ);
Unfortunately, there is no way to do this without comparing all fields that should be equal.
You could solve your problem by using AssertJ. It can do field-by-field recursive comparison with options to ignore fields by name, regex or type.
assertThat(sherlock)
.usingRecursiveComparison()
.ignoringFields("name", "home.address.street")
.isEqualTo(moriarty);
It wouldn't be that hard to roll your own using java reflection, if you don't like the capabilities of the ones you're finding.
java - Check if two objects are equal excluding a few properties - Stack Overflow
clean code - How to define what fields to check for equality? - Software Engineering Stack Exchange
[JUnits] How to compare 2 complex objects without overriding toequals/hashcode methods?
[Solved] Compare two objects excluding some fields - Java
I'd recommend to use Decorator design pattern instead of creating Utils classes or setting parameters to null and restoring then after comparison.
Here is an implement suggestion and in your case you only need to override the equals()
It may works if you create a Class method that recieves two objects of itself and compare them by checking certain properties.
class MyClass {
(...)
public static int compare (MyClass m1, MyClass m2){
if (m1.name == m2.name){ return 1; }
return 0;
}
}
You can also check the 'Comparable' interface (this is a better solution): https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html
Hope it helps :)
I think if there were a one-size-fits-all way to compare objects, then Java (or any language) would make it the default, no?
Equality - like hashing and comparison - should be fast, simple and most importantly referentially transparent.
In the end, the question of what exactly the equals method is for is important. If you don't know, then just leave it as is. Physical comparison makes sense in many use cases, particularly if you have control over when objects are created vs. when they are reused.
Also, rather than trying to design comparison functions meaningful for all cases, write code using things like Comparator and let calling code inject whatever makes the most sense at the call site.
First of all, there are two kinds of classes:
- Classes with "value-type" semantics.
- Classes with "reference" semantics.
You can google these terms to find information about precisely what they mean, and how they differ from each other, for your language of choice.
Every single class with "value-type" semantics must have an equals() method, and this method must take into consideration every single one of its fields, or at least give the illusion that it does so. If it is expensive, bite the bullet and spend clock cycles lavishly, because it is necessary.
Classes with "reference" semantics do not need an equals() method. I would not go as far as to say that they should not have such a method, but if they are to have one, it should be thought of as a utility / helper method which is going to be used in some weird way which is unrelated to the original intent of equals. That's because under normal circumstances, these objects are compared by reference, not by value.
Reference equality is checked using the == operator in Java, while in C#, where the == operator may be overloaded, we use System.Object.ReferenceEquals(). (Though, again, you are not supposed to overload the == operator of a reference-semantics class.)
Incidentally, the kinds of classes that are complex and expensive to check for equality usually tend to be classes with reference semantics, so they do not need an equals() method. And generally, if you have any doubts or second thoughts as to how the equals() method should be implemented, this is a good indication that what you have in your hands is a reference-semantics class, not a value-type-semantics class.
As for hashCode(), the only objects that should implement it are objects that not only have value semantics, but are also immutable. This is because hash containers generally obtain the hash code of an object once, and then cache it for as long as the object resides in the container, so if the object undergoes a mutation, the contents of the object will be in conflict with the cached hash code. It is a very common newbie bug to use a non-immutable object as a key to a hashmap, and a very hard one to track down unless you know where to look first: the immutability of the class used as the key.
So, every class which is not immutable should have a hashCode() method coded as follows:
public int hashCode()
{
assert false; //OMG! hashCode() was invoked on mutable object!
}
So, since only immutable classes should implement hashCode(), ensuring that it works in a way which is in agreement with how equals() works is pretty straightforward, and probably a lot more simple than what you may have feared.
Is there any easier way to compare all the attributes of 2 complex objects without overriding toequals method? The complex object which i am working on has nested objects and the level goes down pretty deep and refactoring of the same is not currently in my scope.
I need to write my test cases to compare 2 such objects and also reporting which all fields are not equal in case the junit test cases fails.