Java 内部对象更改时哈希集哈希的解决方法

Java 内部对象更改时哈希集哈希的解决方法,java,collections,hash,set,hashcode,Java,Collections,Hash,Set,Hashcode,这个问题的答案解释了我面临的问题: 基本上,一旦我向HashSet中添加了一些内容,如果我修改了它的任何字段,那么该集将无法通过任何相等性测试,因为它所存储的hash代码是在它设置了不同字段时使用的 那么,既然这个答案解释了发生的事情,那么对于这个问题来说,有什么好的解决办法,既可以使用集合的唯一性,又可以修改集合中对象的内部字段?或者这是不可能的?从集合中删除要修改的对象,对其进行更改,然后将其重新添加。据我所知,没有标准的Set实现可以处理字段(在hashCode()或compareTo()

这个问题的答案解释了我面临的问题:

基本上,一旦我向HashSet中添加了一些内容,如果我修改了它的任何字段,那么该集将无法通过任何相等性测试,因为它所存储的hash代码是在它设置了不同字段时使用的


那么,既然这个答案解释了发生的事情,那么对于这个问题来说,有什么好的解决办法,既可以使用集合的唯一性,又可以修改集合中对象的内部字段?或者这是不可能的?

从集合中删除要修改的对象,对其进行更改,然后将其重新添加。据我所知,没有标准的
Set
实现可以处理字段(在
hashCode()
compareTo()
实现中使用的字段)在存储时被更改


或者,如果字段未用于确定身份、相等性或位置(即未用于
hashCode()
compareTo
equals()
),则没有问题。

如果您修改的字段不是相等性测试的一部分,它们也不应该是哈希代码计算的一部分。在这种情况下,没有问题:您可以修改这些字段

如果字段是相等性测试的一部分,最干净的方法可能是从集合中删除对象,然后修改并重新插入它


如果是后者,并且您发现自己经常这样做,那么您可能需要重新访问当前问题的数据结构选择。

解决此问题的唯一方法是不使用依赖于任何可变字段的
hashCode()
方法。如果对象具有独立于其字段值的标识和存在性,那么这很容易——使用
System.identityHashCode()
。否则,可以将
hashCode()
基于一个不可变字段。如果没有,那恐怕你就走运了。

使用HashMap而不是HashSet。将密钥定义为不会随时间改变的唯一性。

使用任何其他集合(可能是
链接列表),仅在添加时检查唯一性,如

public class MySetList<E> extends LinkedList<E> implements Set<E> {
    private static final long serialVersionUID = 1L;

    @Override
    public boolean add(E e) {
        return new HashSet<E>(this).add(e) ? super.add(e) : false;
    }
}
公共类MySetList扩展LinkedList实现集{
私有静态最终长serialVersionUID=1L;
@凌驾
公共布尔加法(E){
返回新的HashSet(this).add(e)?super.add(e):false;
}
}

不管投票数多少,选择您的答案,因为它基本上与aix相同,而且是在几秒钟之前出现的:)谢谢。我想我可能会在这个例子中使用集合来重新评估。