【问题标题】:Custom Generic Class as Key to Hash Map Issue自定义泛型类作为哈希映射问题的关键
【发布时间】:2011-06-30 18:14:38
【问题描述】:

我有以下测试代码:

公共静态最终字符串 [] 列表 = { “苹果”、“球”、“猫”、“狗”、“鸡蛋”、“扇子”、“女孩”、“帽子”、“冰屋”、“混蛋” }; ... HashMap, String> hm = new HashMap, String>(); Set> s = new TreeSet>(); 随机 g = new Random(); for(int i=0; i k1 = new DoubleKey(first, second); DoubleKey k2 = new DoubleKey(first, second); s.add(k1); hm.put(k2, 列表[i]); } Set> ts = hm.keySet(); 迭代器> itr = ts.iterator(); 而(itr.hasNext()){ DoubleKey k = itr.next(); System.out.println(k.getFirstKey().toString() + " + " + k.getSecondKey().toString() + " -> " + hm.get(k).toString()); } System.out.println("----"); 迭代器> sItr = s.iterator(); 而(sItr.hasNext()){ DoubleKey k = sItr.next(); 字符串 currStr = hm.get(k); System.out.println(k.getFirstKey().toString() + " + " + k.getSecondKey().toString() + " -> " + currStr); }

我所做的是创建一个自定义通用类 DoubleKey 来包含一个包含两个部分的键。如您所见,Set s 和 HashMap hm 的键具有相同的组件,但实例化方式不同(k1 = k2) .当我尝试使用 shm 上的键 get 一个值时,它返回 null,尽管在第一次打印它会显示正确的映射。

样本输出: 3922 + 2544 -> 女孩 9267 + 3750 -> 帽子 3107 + 10929 -> 苹果 5162 + 8834 -> 风扇 8786 + 1125 -> 猫 10650 + 4078 -> 鸡蛋 3808 + 7363 -> 混蛋 1364 + 7657 -> 狗 1364 + 4412 -> 球 1583 + 1460 -> 冰屋 ---- 10650 + 4078 -> 空 1364 + 4412 -> 空 1364 + 7657 -> 空 1583 + 1460 -> 空 3107 + 10929 -> 空 3808 + 7363 -> 空 3922 + 2544 -> 空 5162 + 8834 -> 空 8786 + 1125 -> 空 9267 + 3750 -> 空

这是我的 DoubleKey 实现:

公共类 DoubleKey,J extends Comparable> 实现 Comparable>{ 私人 K 密钥 1; 私人 J 密钥 2; 公共双键(K key1,J key2){ 这个.key1 = key1; this.key2 = key2; } 公共 K getFirstKey(){ 返回 this.key1; } 公共 J getSecondKey(){ 返回 this.key2; } // 需要 Comparable 接口 public int compareTo(DoubleKey aThat){ // 注意:检查空值 return (this.key1.toString() + this.key2.toString()).compareTo(aThat.key1.toString() + aThat.key2.toString()); } 公共布尔等于(DoubleKey aThat){ return (this.key1.toString() + this.key2.toString()).equals(aThat.key1.toString() + aThat.key2.toString()); } }

这是怎么发生的?如果两个对象(在这种情况下来自自定义泛型)已经用 2 个相同的值实例化,它们是否可以不同 eve3n?我该如何纠正?我希望有人可以在这里帮助我。谢谢!

【问题讨论】:

  • 这里的代码太多了!请你把你的例子删减很多,这样有人可能有耐心看一遍。
  • DoubleKey 类的 hashCode 方法覆盖在哪里?
  • 我尽力解释它。对不起。
  • 我不认为有太多的代码。够了。有时需要一个体面的长度解释。

标签: java generics set hashmap


【解决方案1】:

除了.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 方法比较组件,而不是连接的字符串。

【讨论】:

  • 好点。我没有仔细看他对equals的实现。 1+
  • 好收获,我直接越过那个。我还建议使用 @Override 标记 equals 和 hashCode 以使这样的事情变得明显。
【解决方案2】:

现在学习这一课:如果您重写了 equals 方法(就像您所做的那样),那么您也必须重写 hashcode 方法。该方法用于各种事情,包括在 HashMaps 中查找项目。

【讨论】:

    【解决方案3】:

    DoubleKey 类的 hashCode 方法覆盖在哪里?我不认为它会作为一个正确的键,除非你实现它,否则你的两个对象将被认为是不同的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-16
      • 2011-03-05
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-17
      相关资源
      最近更新 更多