7

所以我有很多自定义类,它们内部也有使用组合的自定义类。

我的自定义类的变量变化非常频繁,我将它们添加到 HashSets。所以我的问题是当我实现 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;
    }
4

3 回答 3

6

Java 中的 Equals 和 hashCode 合约:

当我们重写 equals() 方法时,我们必须重写 hashCode(),Java 中的 equals 方法必须遵循其与 Java 中的 hashCode 方法的约定,如下所述。

  1. 如果两个对象通过 equals() 方法相等,则哈希码必须相同。
  2. 如果两个对象通过 equals() 方法不相等,则哈希码可能相同或不同。

这些是您的类的 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;
    }
于 2013-07-23T04:54:33.890 回答
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;
    }

}
于 2013-07-23T04:50:31.807 回答
1

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

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

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

(添加#2)即使您的 Cell 类是不可变的(两个布尔值没有改变),它也是一个糟糕的散列选择,因为它只有 2 位范围。想象一下,根据他们是男性/女性和蓝眼睛/棕色眼睛来散列所有人。一个很好的开始,但只有 4 个类别,每个类别将有大约 20 亿人。理想情况下,您还有其他几个类别,例如出生年份、出生国家等。

于 2013-07-23T05:08:40.373 回答