0

I have an unusual requirement to implement.

I need to store several objects in a Set.

Let's use this simple class as an example -

class Name { 
    String first; 
    String last; 
    String middle;
}

My business rule is that two Name objects are considered equal if the first, last, and middle fields are all equal OR if first and last fields are equal and one (or both) of the objects has null for the middle field.

So in implementing the hash and equals methods for my Name class I could have a use cases where equals returns true for the two objects but the hash for the two objects returns a different value (because one object has a value for middle and the other object has null for middle).

The actual Set implementation I use cannot be HashSet because HashSet uses the hash method to determine whether or not to add the object to the Set. In my example the hash method will return a different value for these two objects name1 (first=Bruce, last=Phillips, middle=Allen) and name2 (first=Bruce, last=Phillips, middle=null) even though my equals method will return true for the two objects.

My plan is to use TreeSet and have my Name class implement comparable. I don't really care about the order of Name class objects in my TreeSet but by using TreeSet and implementing comparable's compareTo method I can use the equals method in class Name (which checks if one of the objects has null for middle field) to determine if the two object's are equal.

Any drawbacks to this approach to solving my requirement?

Thank you for the help.

Bruce

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
Bruce Phillips
  • 2,740
  • 3
  • 18
  • 17
  • Objects can have the same `hashCode` but may not be `equals`, but the opposite cannot be true. – Alexis King Jun 20 '14 at 21:06
  • OK - how would you implement this requirement? – Bruce Phillips Jun 20 '14 at 21:10
  • 1
    Why can't you write a `hashCode` function that uses the first and last names and ignores the middle name? – ajb Jun 20 '14 at 21:29
  • @ajb - that is likely what I will do - however I will still not be able store the Name objects in a HashSet - HashSet uses the hash value to determine if it should add to the set or replace an existing object in the set. So even if the middle names are different (thus the objects are not equal) the two objects will have the same hash value. – Bruce Phillips Jun 23 '14 at 20:41
  • @BrucePhillips I think you've misunderstood how `HashSet` works. If two objects have the same hash value, it uses `equals` to determine whether the objects are the same or different. The only negative consequence of two objects having the same hash value is that they now have to go on a list attached to a bucket, meaning finding one will take longer. If you write a `hashCode()` function that always returns 1, `HashMap` and `HashSet` will still work correctly but will be as inefficient as searching a linked list. – ajb Jun 23 '14 at 20:43
  • @BrucePhillips See the [javadoc for HashSet#add](http://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html#add-E-). In particular, note the definition of when it considers an object to be "present". _This definition does not use the hash value at all._ – ajb Jun 23 '14 at 20:47

2 Answers2

0

From Javadocs:

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

Vivin
  • 1,327
  • 2
  • 9
  • 28
0

You cannot utilize the Object.equals or Comparator.compare for these business rules as both of these methods require transitive behavior and your rules are not transitive.

Take an example where name1 and name2 have different middle names but name3 has no middle name. As I understand your rules name1 == name3 and name2 == name3. If your rules were transitive this would mean that name1 == name2, which it does not as the middle names are different.

Transitive nature of equals method

Community
  • 1
  • 1
Brett Okken
  • 6,210
  • 1
  • 19
  • 25