如何实现hashCode和equals方法

26

在Java中,我应该如何实现以下类的hashCode()equals()方法?

class Emp 
{
  int empid ; // unique across all the departments 
  String name;
  String dept_name ;
  String code ; // unique for the department 
}

那不是Java源代码。或者你创建了自己的名为string的类?你真的应该看一下这个:http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html - Bart Kiers
1
此外,请参阅:http://www.artima.com/lejava/articles/equality.html,该文章详细说明了如何编写一个Equality方法。 - sateesh
http://marxsoftware.blogspot.in/2011/10/guavas-objects-class-equals-hashcode.html - Emil
使用Eclipse或IntelliJ IDEA为您生成equals()hashCode()。您需要做的就是选择它应该依赖的字段。 - Jiri Kremser
请查看《Effective Java》第8条,详细了解编写equals方法的处理方式。 - Paul Rooney
显示剩余2条评论
6个回答

34

在Eclipse中,右键单击->源代码->生成hashCode()和equals()会得到以下内容:

/* (non-Javadoc)
 * @see java.lang.Object#hashCode()
 */
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (code == null ? 0 : code.hashCode());
    return result;
}
/* (non-Javadoc)
 * @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!(obj instanceof Emp))
        return false;
    Emp other = (Emp) obj;
    return code == null ? other.code == null : code.equals(other.code);
}

我已将代码选择为唯一字段


1
嗯...通常我会在equals()方法中比较所有字段,除非你真的有很强的理由不这样做... - Neil Coffey
1
那么如果来自不同部门的两个 Emp 具有相同的代码,它们是相等的吗?在这种实现中,您至少需要添加 dept_name - Pascal Thivent
我接受这个答案,因为我明白了需要做什么。jutky已经将代码视为唯一标识符。 - Vidya
6
代码if (obj == null) return false;是多余的,因为instanceof已经检查了null。 - Alex Kucherenko
使用 instanceof 进行检查会导致 Sonar 的严重问题。因此最好使用 if (getClass()!=other.getClass()) {return false;}。 - ACV

4

尝试使用这段代码,使用org.apache.commons.lang3.builder库。

public int hashCode() {
    return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
        append(empid).
        append(name).
        append(dept_name ).
        append(code ).
        toHashCode();
}

public boolean equals(Object obj) {

    if (obj == this)
        return true;
    if (!(obj instanceof Person))
        return false;

    Emp rhs = (Emp) obj;
    return new EqualsBuilder().
        // if deriving: appendSuper(super.equals(obj)).
        append(name, rhs.name).
        isEquals();
}

2
Guava提供了帮助方法来创建它们。您只需告诉它要考虑哪些字段,它就会为您处理空值并计算哈希码的质数。IDE也可以根据您选择的字段生成它们。
将其委托给这样的工具的优点是您将获得一个标准解决方案,并且不必担心在项目中分散实现的错误和维护问题。
以下是使用Guava和由IntelliJ插件生成的示例:https://plugins.jetbrains.com/plugin/7244?pr=

0
如果代码是唯一的(即您的业务键),最好只使用代码进行equals和hashCode - 将业务键(代码)与对象ID(id)分开是一个好习惯。
这里有一篇不错的文章:Hibernate文档:Equals和HashCode(不仅适用于Hibernate本身)。

1
这似乎是一个部门独有的,这表明不同部门可以共享相同的“代码”。总之,如果你问我,这是一个相当模糊的问题。 - Bart Kiers

-1
无论您在equals中使用哪些值来确定两个对象是否相同,都是您需要用来创建哈希码的值。
public boolean equals(Object o) {

    boolean result = false;

    if(o instanceof CategoryEnum) {

        CategoryEnum ce = (CategoryEnum) o;
        result = ce.toString().equals(name);

    }       
    return result;

}


public int hashCode()
{
  int hash = 6;
  hash += 32 * name.hashCode();
  return hash;
}   

3
这并不完全准确。只使用子集进行hashCode是完全合法的(例如,用于equals的代码和名称,仅使用代码进行hashCode)。甚至可以使用常数hashCode(public int hashCode() {return 42;})——这会破坏散列集合(HashMap、HashSet等)的性能,但它们仍然能够正常工作。因此,这比一个无效的hashCode方法要好。唯一的规则是:如果两个对象相等(a.equals(b)),则它们必须具有相同的哈希码(a.hashCode() == b.hashCode())。如果它们不相等,则哈希码仍可能相等。 - sfussenegger

-2

equals()和hashCode(),它们在很多不同的地方都有应用。

equals(),如果我们没有从Object类中覆盖它,那么它表示两个变量是否指向同一个对象堆?

public  Class Student(){
  private int id;
  private  name;
  public Student(int id,String name){
  this.name=name;
  this.id=id; 
}

public void main(String[] args){
  Student A=new Student(20,'Lily');
  Student B=new Student(20,'Lily');
  boolean flag=A.equals(B)//flag=flase;
/*
 *Although they attribute the same, but they are two different objects, they point to     different memory
 */


@Override
public boolean equals(Object obj) {


  if (obj == null) {
    return false;
  }
  if (this == obj) {
    return true;
  }

  if (this.getClass() != obj.getClass()) {
    return false;
  }
  Student s=(Student)obj;
  return new Integer(this.id).equals(new Integer(s.id))&&this.name.equals(s.name);
  }

/**
  *Sometimes even though we Override  the equals, but we still can not determine whether   the *two objects the same,
  *In the collection object, such as HashSet, this time we have to Override the hashoCode ()
  */

public int hashCode(){
  return id + name.hashCode() ;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接