Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using multiple alternatives of hashCode() and equals() for sets

Suppose I have a simple POJO class Class1 , and it has 2 fields of type int.

I've implemented the hashCode() and equals() methods of it to handle exactly those 2 fields, in order to put instances of the class into a set.

So far so good.

Now, I want to have a different set, which considers instances of Class1 to be equal if the first field is equal , making the equality condition weaker. I might even want to have another set which considers only the second field as the one that checks for equality.

Is it possible? If so, how?

like image 244
android developer Avatar asked Jun 12 '13 05:06

android developer


2 Answers

You can get that effect by using a TreeSet when providing a custom Comparator that only inspects the fields you're interested in.

Note, however, that strictly speaking such a TreeSet no longer is a "correct" Set because it effectively ignores the equal() method of your objects:

Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.

like image 96
Joachim Sauer Avatar answered Sep 22 '22 15:09

Joachim Sauer


The standard Java libraries don't support this.

And (surprisingly) there doesn't appear to be a Map or Set class in the Apache Commons Collections or Guava libraries that supports this.

There are probably other libraries that to support this if you look hard enough.

Alternatively, you could write your own ... starting with the standard HashMap code.


A cheap-and-cheerful alternative is to create a light-weight wrapper class for your element type that delegates most methods to the wrapped class and provides a different equals / hashcode pair to the original. There is a small runtime penalty in doing this ... but it is worth considering.

Joachim's suggestion is good too, unless your sets are likely to be particularly big. (TreeSet has O(logN) lookup compared with O(1) for a properly implemented hash table.)

like image 33
Stephen C Avatar answered Sep 25 '22 15:09

Stephen C