Wednesday, July 16, 2008

Java Set / HashSet API

Recently I was confronted with a problem.  I have two Sets of objects
S1: f1, f2, f3
S2: f1, f2, f3
Where S1.f1 != S2.f1 and S1.f1.equals(S2.f1) are both true.
The two Sets each represent the same object identities but they are being evaluated in different contexts.  At some point later in time I need to find out the differences between S1.f1 and S2.f1
Now Set has some great methods on it like:
contains(Object o)
remove(Object o)
And then there's HashSet which is a set backed by a sweet sweet HashMap, which should make it fast to do contains() + remove().
So what I need to do at some point is:
for( F f : S1) {
    F fLocal = S2.get(f);
   //do some comparisons between fLocal and f
but I can't.  The Set nor the HashSet API have a get(Object o).  They make the assumption that if .equals() returns true there are no differences between the two objects.  I think I disagree with this premise.  At least in my recent experience .equals() is talking about an ID of an object. With that ID I wish to track the state of that object evaluated in different contexts.  
Maybe this is abuse of .equals() and I should get over myself.  But I wish Java's API's left it up to me to decide the meaning of .equals() and leave their API's a little more open ended.
Maybe it's not part of the core API, but at least they could have implemented this in HashSet.


dpierkowski said...

I don't know if this helps or not, but TreeSet takes a Comparator. So rather than implementing a single .equals on your F class you can construct two different TreeSet of F, each with it's own context specific Comparator instance.

(And can I just say how proud I am of myself for responding in a timely fashion for once...)

Eric said...

I still have an issue with putting the method you describe in the core API. I think it would be more confusing than functional.

But I don't really see an issue with adding it to HashSet. Sigh. I wish I did, though...

Web Statistics