2012-11-05 28 views
1

我已经定义了一个名为SetOb一个简单的私有类,它包含一个INT设置数据结构。我在'main'方法中有一个HashMap,其中SetOb为Key和Integer作为值。现在您可以在主要方法中看到,当我使用SetOb实例提供HashMap,然后查找具有完全相同值的实例时,它将返回'null'。在我使用我自己定义的数据结构(如SetOb)作为HashMap中的键时,这种情况在我之前发生过很多次。有人能告诉我我错过了什么吗? 请注意,在SetOb类的构造函数中,我将Set passed as参数复制。的HashMap java中无法散列的MyObject

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"); 
    } 

} 

回答

2

xy是不一样的对象实例因此包含无法匹配yx,这最终没有找到在地图匹配键/值。

如果您希望匹配成功,请执行(覆盖)hasCode & equals方法SetOb它将比较字段值。

样品的方法(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; 
} 
+0

感谢Yogendra,它的工作就像一个魅力:) –

2

SetOb需要重写hashCode()因此equals()方法。

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

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(); 
    } 
} 
+0

当你说_object_身份,你的意思reference_ _identity?谢谢(你的)信息。 –

+0

@DeepakGarg - 的确如此。通过对象标识,两个不同的对象永远不会被视为相等(尽管它们在理论上可能具有相同的散列码)。因此,不能将另一个替换为散列表查找的关键。 –