我有以下测试代码:
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); }
我所做的是创建一个自定义通用类 DoubleKey
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()); } }
这是怎么发生的?如果两个对象(在本例中来自自定义泛型)使用 2 个相同的值实例化,它们是否可以不同?我该如何纠正这个问题?我希望有人能在这里帮助我。谢谢!
最佳答案
除了 .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 方法比较组件,而不是连接的字符串。
关于java - 自定义通用类作为 HashMap 问题的关键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5057504/