为自定义类实现hashcode和equals

时间:2013-07-23 04:41:18

标签: java equals hashcode abstract-data-type custom-object

所以我有很多自定义类,其中也有使用组合的自定义clases。

我的自定义类包含非常频繁更改的变量,我将它们添加到HashSet。所以我的问题是当我实现hashCode时 - 对于只有不断变化的私人领域的班级,我该怎么做?

以下是一个自定义类的示例:

public class Cell {
    protected boolean isActive;
    protected boolean wasActive;

    public Cell() {
    this.isActive = false;
    this.wasActive = false;
    }

    // getter and setter methods...

    @Override
    public int hashCode() {
    // HOW SHOULD I IMPLEMENT THIS IF THIS custom object is constantly
        // being added into HashSets and have it's private fields isActive
        // and wasActive constantly changed.
    }

    // ANOTHER QUESTION Am I missing anything with this below equals implementation?
    @Override
    public boolean equals(Object object) {
    boolean result = false;
    if (object instanceof Cell) {
        Cell otherCell = (Cell) object;
        result = (this.isActive == otherCell.isActive && this.wasActive == 
            otherCell.wasActive);
    }
    return result;
    }

3 个答案:

答案 0 :(得分:4)

Java中的Equals和hashCode契约:

当我们覆盖equals()方法时,我们必须覆盖hashCode(),Java中的equals方法必须遵循与Java中的hashCode方法的契约,如下所述。

  1. 如果两个对象等于equals()方法,那么hashcode必须 是一样的。
  2. 如果两个对象不等于equals()方法,那么就会出现哈希码 可以相同或不同。
  3. 这些是您的类的equals和hashcode方法的示例实现:

     //Hashcode Implementation    
    
       @Override
        public int hashCode() 
        {
            final int prime = 31;
            int result = 1;
            result = prime * result + (isActive ? 1231 : 1237);
            result = prime * result + (wasActive ? 1231 : 1237);
            return result;
        }
    
    //equals Implementation    
        @Override
        public boolean equals(Object obj) 
        {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Cell other = (Cell) obj;
            if (isActive != other.isActive)
                return false;
            if (wasActive != other.wasActive)
                return false;
            return true;
        }
    

答案 1 :(得分:1)

以下是具有私有字段的类的示例。

public class Test {

    private int num;
    private String data;

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if ((obj == null) || (obj.getClass() != this.getClass()))
            return false;
        // object must be Test at this point
        Test test = (Test) obj;
        return num == test.num
                && (data == test.data || (data != null && data
                        .equals(test.data)));
    }

    public int hashCode() {
        int hash = 7;
        hash = 31 * hash + num;
        hash = 31 * hash + (null == data ? 0 : data.hashCode());
        return hash;
    }

}

答案 2 :(得分:1)

你是SOL。在标准Java集合中的键中使用hashCode()的地方,它不应该更改。否则你需要一个类似HashSet的自定义实现。

仅使用不变的字段(或者,如果您大胆并且不介意偶尔崩溃,很少更改字段)来计算hashCode()。

(添加)。在您的特定示例中,使用Object.hashCode()。

(添加#2)即使你的Cell类是不可变的(两个布尔值没有改变),它也很难选择散列,因为它只有2位的范围。想象一下,无论是男性还是女性,蓝眼睛/棕色眼睛,都会让所有人感到震惊。一个非常好的开始,但只有4个类别,每个类别将有20亿人。理想情况下,您还有其他几个类别,如出生年份,出生国家等。