【问题标题】:HashMap in java cannot hash MyObjectjava中的HashMap不能散列MyObject
【发布时间】:2012-11-05 02:21:03
【问题描述】:

我定义了一个名为 SetOb 的简单私有类,其中包含一个 int 和一个 Set 数据结构。我在 'main' 方法中有一个 HashMap,其中 SetOb 作为键,整数作为值。现在您可以在 main 方法中看到,当我向 HashMap 提供 SetOb 实例,然后寻找具有完全相同值的实例时,它返回“null”。在我使用自己定义的数据结构(如 SetOb)作为 HashMap 中的 Key 之前,这种情况已经发生过好几次了。有人可以指出我错过了什么吗? 请注意,在 SetOb 类的构造函数中,我复制了作为参数传递的 Set。

public class Solution {

    public static Solution sample = new Solution();
    private class SetOb {
        public int last;
        public Set<Integer> st;
        public SetOb(int l , Set<Integer> si ){
            last = l;
            st = new HashSet<Integer>(si);
        }
    }

    public static void main(String[] args) {
        Map<SetOb, Integer> m = new HashMap< SetOb, Integer>();
        Set<Integer> a = new HashSet<Integer>();

        for(int i =0; i<10; i++){
            a.add(i);
        }
        SetOb x = sample.new SetOb(100, a);
        SetOb y = sample.new SetOb(100, a);
        m.put(x,500);
        Integer val = m.get(y);
        if(val!= null) System.out.println("Success: " + val);
        else System.out.println("Failure");
    }

}

【问题讨论】:

    标签: java hashmap hashset


    【解决方案1】:

    您的 xy 不是同一个对象实例,因此 contains 无法将 yx 匹配,最终无法在地图。

    如果您希望匹配成功,请在SetOb 中实现(覆盖)hasCode & equals 方法,该方法将比较字段值。

    示例方法(Eclipse 生成)如下:

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + last;
        result = prime * result + ((st == null) ? 0 : st.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        SetOb other = (SetOb) obj;
        if (last != other.last)
            return false;
        if (st == null) {
            if (other.st != null)
                return false;
        } else if (!st.equals(other.st))
            return false;
        return true;
    }
    

    【讨论】:

      【解决方案2】:

      hashCode 的默认实现使用对象标识 来确定哈希码。如果你想要值标识,你需要在你的私有类中实现hashCode(和equals)。例如:

      private class SetOb {
          public int last;
          public Set<Integer> st;
          public SetOb(int l , Set<Integer> si ){
              last = l;
              st = new HashSet<Integer>(si);
          }
          @Override
          public boolean equals(Object other) {
              if (other.class == SetOb.class) {
                  SetOb otherSetOb = (SetOb) other;
                  return otherSetOb.last == last && otherSetOb.st.equals(st);
              }
              return false;
          }
          @Override
          public int hashCode() {
              return 37 * last + st.hashCode();
          }
      }
      

      【讨论】:

      • 当您说 object 身份时,您的意思是 identity by reference 吗?感谢您的信息。
      • @DeepakGarg - 没错。使用对象标识,两个不同的对象永远不会被视为相等(即使它们可以,理论上具有相同的哈希码)。因此,一个不能替代另一个作为哈希表查找的键。
      【解决方案3】:

      SetOb 需要覆盖 hashCode()equals() 方法。

      基于哈希的集合使用这些方法来存储 (hashCode()) 和检索 (hashCode()) 和 equals()) 您的对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-15
        • 2023-03-11
        • 2016-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-26
        • 2023-01-14
        相关资源
        最近更新 更多