我有以下测试代码:
public static final String[] list = { "apple","ball","cat","dog","egg","fan","girl","hat","igloo","jerk" }; ... HashMap<DoubleKey<Integer, Integer>, String> hm = new HashMap<DoubleKey<Integer, Integer>, String>(); Set<DoubleKey<Integer, Integer>> s = new TreeSet<DoubleKey<Integer, Integer>>(); Random g = new Random(); for(int i=0; i<10; i++){ int first = g.nextInt(9999) + 1000; int second = g.nextInt(9999) + 1000; DoubleKey<Integer, Integer> k1 = new DoubleKey<Integer, Integer>(first, second); DoubleKey<Integer, Integer> k2 = new DoubleKey<Integer, Integer>(first, second); s.add(k1); hm.put(k2, list[i]); } Set<DoubleKey<Integer, Integer>> ts = hm.keySet(); Iterator<DoubleKey<Integer, Integer>> itr = ts.iterator(); while(itr.hasNext()){ DoubleKey<Integer, Integer> k = itr.next(); System.out.println(k.getFirstKey().toString() + " + " + k.getSecondKey().toString() + " -> " + hm.get(k).toString()); } System.out.println("----"); Iterator<DoubleKey<Integer, Integer>> sItr = s.iterator(); while(sItr.hasNext()){ DoubleKey<Integer, Integer> k = sItr.next(); String currStr = hm.get(k); System.out.println(k.getFirstKey().toString() + " + " + k.getSecondKey().toString() + " -> " + currStr); }
我所做的是创建一个Custom Generic Class DoubleKey&lt; K,J&gt;包含具有两个部分的键。如您所见,Set s 和HashMap hm 的键具有相同的组件,但实例化方式不同( k1 = k2 ) 。当我尝试使用 s 上的键获取值 hm 时,它会返回 null ,但是首先打印它显示正确的映射。
Sample Output: 3922 + 2544 -> girl 9267 + 3750 -> hat 3107 + 10929 -> apple 5162 + 8834 -> fan 8786 + 1125 -> cat 10650 + 4078 -> egg 3808 + 7363 -> jerk 1364 + 7657 -> dog 1364 + 4412 -> ball 1583 + 1460 -> igloo ---- 10650 + 4078 -> null 1364 + 4412 -> null 1364 + 7657 -> null 1583 + 1460 -> null 3107 + 10929 -> null 3808 + 7363 -> null 3922 + 2544 -> null 5162 + 8834 -> null 8786 + 1125 -> null 9267 + 3750 -> null
这是我的DoubleKey实现:
public class DoubleKey<K extends Comparable<K>,J extends Comparable<J>> implements Comparable<DoubleKey<K,J>>{ private K key1; private J key2; public DoubleKey(K key1, J key2){ this.key1 = key1; this.key2 = key2; } public K getFirstKey(){ return this.key1; } public J getSecondKey(){ return this.key2; } // need for Comparable interface public int compareTo(DoubleKey<K,J> aThat){ // NOTE: check for nulls return (this.key1.toString() + this.key2.toString()).compareTo(aThat.key1.toString() + aThat.key2.toString()); } public boolean equals(DoubleKey<K,J> aThat){ return (this.key1.toString() + this.key2.toString()).equals(aThat.key1.toString() + aThat.key2.toString()); } }
是怎么回事?如果两个objecst(在这种情况下来自自定义泛型)可以使用2个相同的值进行实例化,那么它们是不同的eve3n吗?我怎么能纠正这个?我希望有人可以帮助我。谢谢!
答案 0 :(得分:4)
除了.hashCode()
之外,你应该有equals(Object)
的实现,而不是(仅)equals(DoubleKey<...>)
,因为否则你将有两个独立的方法(只有第一个是实际上是由HashMap调用的)。这是一个提案:
public boolean equals(Object other) {
if(this == other)
return true;
if(!(other instanceof DoubleKey))
return false;
DoubleKey that = (DoubleKey)other;
return (this.key1 == null ? that.key1 == null : this.key1.equals(that.key1)) &&
(this.key2 == null ? that.key2 == null : this.key2.equals(that.key2));
}
hashCode方法也应该适合这个,例如:
public int hashCode() {
return key1.hashCode() * 3 + key2.hashCode() * 5;
}
您的key1.toString()+key2.toString()
比较有点危险,因为它允许(1, 21).equals((12,1))
为真,这通常不是故意的。 compareTo方法也是如此 - 使用compareTo方法比较组件,而不是连接的字符串。
答案 1 :(得分:3)
立即学习本课程:如果覆盖equals方法(就像你所做的那样),那么你必须覆盖hashcode方法。该方法用于各种事情,包括在HashMaps中查找项目。
答案 2 :(得分:1)
DoubleKey类的hashCode方法在哪里覆盖?我不认为它会作为一个正确的键工作,除非你实现这个,否则你的两个对象将被视为不同。