2014-09-19 74 views
1

我有最终字符串作为唯一ID的类。当然,我想重写equals,因此比较仅基于ID。是否正确的做法是只返回ID的哈希码,如下所示?我可以使用班级成员的散列码吗?

class ItemSpec{ 
    final String name; 

    ... 

    @Override 
    public boolean equals(Object o){ 
     if(o != null && o instanceof ItemSpec){ 
      return name.equalsIgnoreCase(((ItemSpec)o).name); 
     } else{ 
      return false; 
     } 
    } 

    @Override 
    public int hashCode(){ 
     if(name == null){ 
      return 0; 
     } else{ 
      return name.hashCode(); 
     } 
    } 
} 
+4

是的,这是确定.. – 2014-09-19 15:05:13

+7

请注意,您的'equals'方法假定'name'不是null,但是你的'hashCode'方法假定它可能是。这是什么? – 2014-09-19 15:07:12

+0

@JonSkeet对不起,我注意到添加后。编辑。 – NoMercyIncluded 2014-09-19 15:15:18

回答

12

如果您的等于不区分大小写,则不需要。你可以有两个ItemSpec出来相等,但有不同的哈希码。这打破了散列码最关键的要求。

您的equals必须同意您的hashCode。所以如果你打算比较不区分大小写,你必须写你的hashCode不区分大小写。

@Override 
public int hashCode(){ 
    if (name == null){ 
     return 0; 
    } else{ 
     return name.toLowerCase().hashCode(); 
    } 
} 

而且你hashCode方法意味着name可能为空。如果是这样,你应该在你的equals方法中对它进行无效检查。

+2

不能有'a.equalsIgnoreCase(b)'但是'a.toLowerCase()。equals(b.toLowerCase())'为假的情况吗? – assylias 2014-09-19 15:09:58

+1

很好的结果,但想指出一样assylias:转换可能打开一个特定语言环境和unicode相关的麻烦的大门... – Marco13 2014-09-19 15:10:53

+0

好吧,我意识到我自己和编辑,但你先生是太快我); – NoMercyIncluded 2014-09-19 15:14:06

-1

我没有看到你的方法有任何问题。

但是,我经常看到以下实现:

public int hashCode() { 
    final int prime = 31; 
    int result = super.hashCode(); 
    result = prime * result + ((name == null) ? 0 : name.hashCode()); 
    return result; 
} 

更新: 这里是一个更好的解释链接: Best implementation for hashCode method

+0

这看起来像自动生成的代码,除了增加计算时间之外,没有太大的作用... – assylias 2014-09-19 15:12:50

+5

如果您不需要在您的平等中使用“super.equals”,则不能将'super.hashCode'并入您的哈希码方法。否则两个相等的对象可能会得到不同的哈希码。 – khelwood 2014-09-19 15:13:38

+0

我从我的项目中获取了此代码。我不是100%确定的,如果我手动完成的,或者它是由Eclipse生成的。但我确实看过最常见的实现hashCode的方法,在我看来这是最常见的方法。 – 2014-09-19 15:25:18