1

有什么好的建议如何处理存储在集合中的可变对象?

一些对象可以根据它们的内部状态定义它们的相等性(和 hashCode)。当这些对象存储在集合中,在受控代码之内或之外时,状态的突变可能会导致集合中的不一致。

除了不这样做之外,是否有任何“最佳实践”来避免或处理它?

示例代码:

static class A {
   String s;
   public boolean equals(Object o) {
      return s.equals(((A)o).s);
   }
   public int hashCode() { 
      return s.hashCode();
   }
   public String toString() {
      return s;
   }

}

public static void main(String[] args) {
  A a0 = new A();
  a0.s = "Hello";
  A a1 = new A();
  a1.s = "World";

  HashSet<A> set = new HashSet<A>();
  set.add(a0);
  set.add(a1);

  System.out.println(set);

  a0.s = "World";

  System.out.println(set);
 }
4

2 回答 2

3

在某些时候,开发团队在处理实体集合时遇到了很多这个问题,这些实体集合在存储到数据库之前只获得了它们的密钥。他们的哈希码/等于取决于那个键......

我们提出的解决方案是这样的:

public static <P> void rearrange(Set<P> set) {
    HashSet<P> temp = new HashSet<P>();
    temp.addAll(set);
    set.clear();
    set.addAll(temp);
}

另一个想法是装饰一个 HashSet 的 Set 实现,但我们很快决定从长远来看这会导致更多问题。在大多数情况下,上述方法是由“框架”代码对开发人员透明地执行的,但我对这个解决方案仍然不是特别满意。

于 2013-01-31T09:46:19.623 回答
0

Set接口不提供任何获取值的方法,这样做是有原因的。 Java 集 API

所以它不期望你得到一个值,修改它然后再次添加它。在您的代码中,这就是您所做的;您修改了 Set 中存储的值。

所以理想情况下你应该避免它,但如果你想修改 Set 中的任何对象,请执行以下步骤:

  1. 从集合中移除对象
  2. 添加一个新的修改对象

这样,您的哈希码/平等合同将得到保证。

于 2013-01-31T09:55:28.733 回答