开发者

For a HashMap that maps from a custom class, how to make it so that two equivalent keys will map to say value?

I have a custom class, for example's sake let's say it's tuples without order.

public class UnorderedTuple {  
    Integer i1 = null; Integer i2 = null;

    UnorderedTuple(Integer int1, Integer int2) { i1 = int1; i2 = int2; }

    boolean equals(UnorderedTuple t) { return t.i1 == i1 && t.i2 == t2 || t.i2 == i1 && t.i1 == i2; }
}

Like I said, a dumb example. Now, let's say i have

Map<UnorderedTuple, Integer> m = ne开发者_Python百科w HashMap<UnorderedTuple, Integer>();

Ideally, I'd like this functionality:

UnorderedTuple ut1 = new UnorderedTuple(1,2);
UnorderedTuple ut2 = new UnorderedTuple(2,1);

m.put(ut1,2);
m.put(ut2,3);
System.out.println(m.get(ut1)==3); //ideally returns true

Is there something I need to implement or extend such that I can have this functionality? In the same way that if you use 2 different, but equal strings, or Integers, or whatever as a key it will map it properly, but if I implement this as written, it treats ut1 and ut2 separately. Even if I construct ut1 and ut2 identically, it does the same thing.

Thanks for your help.


You need to override hashCode()... in this case you'd probably do it by XORing the hash codes of all the fields involved, to get the order-independence you want.

You also need to override equals(Object) rather than just implementing equals(UnorderedTuple).

I also note that you're using "==" to compare instances of Integer: don't do that. It will work in the test case you've given due to the rules around boxing, but if you try it with values over 127 you may well run into problems - it's only comparing references rather than values. Call equals to compare values properly.


You need to implement hashCode() in a way that is consistent with equals() (in other words, if a.equals(b) returns true, then a.hashCode() == b.hashCode() must be true as well).

Chapter 3 of Effective Java (free PDF!) has all the nitty-gritty details!

Edit: an you also need to make sure that you're actually implementing equals(Object). In your sample code you only implement equals(UnorderedTuple), which is not the same!


Did you implement equals() and hashCode()? That could be the problem. Link to docs javadoc


Implement hashCode


You will have to define a custom hash function which would evaluate to the same value for both of the tuples. This however is a non-trivial as the hash function is important in determining the performance of the hashmap.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜