java - 可变对象和 hashCode

标签 java immutability hashcode hashset

有以下类:

public class Member {
private int x;
private long y;
private double d;

public Member(int x, long y, double d) {
    this.x = x;
    this.y = y;
    this.d = d;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + x;
    result = (int) (prime * result + y);
    result = (int) (prime * result + Double.doubleToLongBits(d));
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj instanceof Member) {
        Member other = (Member) obj;
        return other.x == x && other.y == y
                && Double.compare(d, other.d) == 0;
    }
    return false;
}

public static void main(String[] args) {
    Set<Member> test = new HashSet<Member>();
    Member b = new Member(1, 2, 3);
    test.add(b);
    System.out.println(b.hashCode());
    b.x = 0;
    System.out.println(b.hashCode());
    Member first = test.iterator().next();
    System.out.println(test.contains(first));
    System.out.println(b.equals(first));
           System.out.println(test.add(first));

}

}

它产生以下结果:
30814 29853 错误的 真的 是的

因为 hashCode 依赖于对象的状态,它不能再被正确地检索,所以包含检查失败。 HashSet 不再正常工作。一个解决方案是让 Member 不可变,但这是唯一的解决方案吗?添加到 HashSets 的所有类都应该是不可变的吗?有没有其他办法处理这种情况?

问候。

最佳答案

散列集中的对象应该要么是不可变的,或者您需要遵守纪律,在它们被用于散列集(或散列映射)之后不要更改它们。

在实践中,我很少发现这是一个问题——我很少发现自己需要使用复杂的对象作为键或设置元素,而且当我这样做时,不改变它们通常不是问题。当然,如果此时您已经公开了对其他代码的引用,这可能会变得更加困难。

关于java - 可变对象和 hashCode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4718009/

相关文章:

clojure - 是否应将延迟视为不可变值?

Hibernate:什么时候需要实现 equals() 和 hashCode(),如果需要,如何实现?

Java:对象为双 "hash"函数,在 [0,1) 上均匀分布

java - Android BroadcastReceiver onReceive 在 MainActivity 中更新 TextView

Java/SQLite - 如何编译 -DTHREADSAFE=1?

java - 如何在 Spring 测试中仅重新创建选定的 Spring 上下文?

java - Hadoop MapReduce 不处理/输出错误?

c# - 消息传递类应该是不可变的吗?

c++ - 如何在 C++ 中创建不可变结构?

java - hashCode 在 Java 中如何工作