1

I have a four domain objects in my project. They have 3 common attributes namely id, name and age.

public class Domain1 {
 private String id;
 private String name;
 private int age;
 ...
}
public class Domain2 {
 private String id;
 private String name;
 private int age;
 ...
}
public class Domain3 {
 private String id;
 private String name;
 private int age;
 ...
}
public class Domain4 {
 private String id;
 private String name;
 private int age;
 ...
}

Domain1 and Domain4 comparison is only based on 'id' attribute when compared with other domains (Domain2, Domain3 and Domain4) or with each other. Domain2 and Domain3 comparison is based on id, name and age except when compared to each other.

For ex,

Domain1 equal Domain2 - equality based on id
Domain1 equal Domain3 - equality based on id
Domain1 equal Domain4 - equality based on id
Domain2 equal Domain3 - equality based on id, name and attribute
Domain2 equal Domain4 - equality based on id
Domain3 equal Domain4 - equality based on id

so on...

How can implement such a equality requirement?

Jon Skeet
1.5m892 gold badges9.3k silver badges9.3k bronze badges
asked Oct 20, 2015 at 16:20
1
  • 3
    I would generally say that making an instance of one type equal to an instance of another type is a bad idea. I can't remember ever seeing that implemented correctly and usefully. Commented Oct 20, 2015 at 16:37

3 Answers 3

2

I would just try not to do this. The rules you've suggested violate the requirements of Object.equals, in particular:

It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.

Now consider your rules with:

Domain1 d1 = new Domain1("id1", "name1", "attribute1");
Domain2 d2 = new Domain2("id1", "name1", "attribute1");
Domain3 d3 = new Domain3("id1", "name3", "attribute3");

Now d2.equals(d1) is true (they match on ID) and d1.equals(d3) is true (they match on ID) but d2.equals(d3) is false, because they don't match on attribute and name.

I don't think I remember ever seeing equality across entirely disparate types working out nicely. It's hard enough trying to avoid surprises in a superclass/subclass relationship, but this is worse.

answered Oct 20, 2015 at 16:42
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks @Jon for the feedback. You are right that this is not a correct equality use case. Its like partial match in some cases. Is there a any other way to achieve this like using comapreTo or by some pattern matching?
@user3222372: Well we don't know what you're trying to achieve with this non-standard matching, which makes it hard to tell you how to accomplish it, beyond saying "don't do it this way".
I basically apply business rule on domain object which are equal based on above equality rule. We need to store this objects in some data structure and apply business rule.
@user3222372: That's still too vague. You could easily create a map of objects by ID, and then find objects with a matching ID, for example, without trying to claim that the objects themselves are equal.
Can you provide some more details on this? I am also good to implement this using some data structure like Map. How can I have an identifier which can work for all types of domain ?
|
1

You can just override the equals() method for those four domain objects according to your requirements. You can generate it through your IDE and modify it to fit your requirements.

Edit: In your method you can look for the type of the object that you are comparing to:

public boolean equals(Object object){
 if(object instancof Domain4) //Specific implementation
 ....
}

However, like Jon said it would violate the requirements of Object.equals.

answered Oct 20, 2015 at 16:24

3 Comments

Thanks @talhouarne. My requirement is that if I call domain1.equals(domain2) or domain2.equals(domain1) it should do equality based on id. If I do domain2.equals(domain3), it should do equality based on id, name and attribute. How can I have two different implementation in domain2?
@talhouarne, I also don't prefer this way. Is there any other way to achieve this in a better way? We keep on introducing new domains to our project so it would be great if we can get a good solution here.
Well you could use a different method - it doesn't have to be equals. It could be isEqualTo() for example
0

Maybe I'm not understanding the use case here, but you could try using a Comparator and then create a ComparableDomain interface that has something like getType (this returns Domain1, Domain2, etc) as well as the common getters/setters (for name, age, and id) and you make all your Domains implement the ComparableDomain.

Now you can compare two different Domain objects by first asking their type and then proceeding to check the fields as you described.

public class DomainComparator implements Comparator<ComparableDomain>{
 @Override
 public int compare(ComparableDomain domain1, ComparableDomain domain2) {
 //First check domain1 and domain2 are actually ComparableDomain objects
 if(domain1.getType().equals("Domain1") && domain2.getType().equals("Domain2")){
 // Do comparison between d1 and d2
 }
 ...
 elseif(domain1.getType().equals("Domain2") && domain2.getType().equals("Domain3"){
 // Do comparison based on id, name and attribute
 }
 }
}

This might not be very elegant but it seems like it could solve the issue. Or maybe I just misunderstood the problem. I know Comparators are usually used for sorting and such, but in this case it might work.

answered Oct 20, 2015 at 17:13

3 Comments

Thanks @Acapulco. You understood the problem correctly. This solution will work if number of domains does not grow. We keep on adding new domain and this design will not be sustainable in future.
Yes, I figured maintaining this is hard. Another more convoluted option would be to parameterize the comparison via a configuration file. Whenever you create a DomainComparator, you load the config file and set the rules for comparing different types of domains. That way you could make it as flexible as you want. The downside is that you would need to program the little config loader and make sure the rules work as expected, etc. However I have found that for a lot of problems, having an external config file that determines the behavior of an internal component might make things much easier
So you can define a sort of table that would look like a transition table for a state machine, and then you can make a cross on a row and a column (two domain types) and the actual matrix index specified by that row and column would let you know what exactly to compare, or even if the two domains are even comparable to start with. That means the rules for comparison are determined by the row/column cross. Now it would be a matter of defining what that rule would look like. It could be a bitmap (1 bit for each property you want to compare, so 101 could be compare id, ignore name, compare age)

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.