java - 当我向 java HashSet 添加一个元素时,所有元素都会发生变化

标签 java hashset

在康威生命游戏模拟器中,我有八个如下所示的代码块来查找单元格的邻域。

int count = 0;
    p.setLocation(p.x-1, p.y-1); //upper left
    if( data.contains(p) ) ++count;
    else if( addingDeadCells ) {
        deadCellsToCheck.add(p);
        for( Point z : deadCellsToCheck ) 
            System.out.println(z.toString() + " " + z.hashCode()); 
        System.out.println();
    }

p是代表当前单元格的点,data是包含 Activity 单元格的HashSet。为了提高效率,我只检查与活细胞相邻的死细胞,因此 deadCellsToCheck 是另一个 HashSet,它在每一代开始时都是空的。每次我执行 deadCellsToCheck.add(p) 时,似乎其中已有的所有单元格都被覆盖为刚刚添加的单元格,因为输出如下所示:

java.awt.Point[x=0,y=0] 0

java.awt.Point[x=1,y=0] 1072693248
java.awt.Point[x=1,y=0] 1072693248

java.awt.Point[x=2,y=0] 1073741824
java.awt.Point[x=2,y=0] 1073741824
java.awt.Point[x=2,y=0] 1073741824
etc...

出于多种原因,我认为这不可能。有什么想法吗?

最佳答案

此问题的原因是您的 HashSet 多次包含相同的 Point 实例。您应该创建一个新点并将其添加到集合中,而不是编辑点 p.setLocation(p.x-1, p.y-1);:

int count = 0;
p = new Point(p.x-1, p.y-1); // new point here
if (data.contains(p)) {
     count++;
} else if (addingDeadCells) {
    deadCellsToCheck.add(p);
    for (Point z : deadCellsToCheck)  {
        System.out.println(z.toString() + " " + z.hashCode());
    }
    System.out.println();
}

您当前的结构也违反了 hashCode() 方法的约定:

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer

集合使用hashCodeequals方法来消除重复。您创建具有 hashcode = 0 的点 (0,0)。然后,您将该点修改为 (1,0),其哈希值更改为 1072693248,因此该集合允许再次插入该点。但它是同一个实例 - 它是在集合中插入两次的同一个对象。

可变对象通常不应在依赖 hashcode 方法的集合或其他数据结构中使用。

解决方案是使点不可变(如果您使用java.awt.Point,我建议创建您自己的类):

public class Point {

     private final int x;
     private final int y;

     public Point(int x, int y) {
         this.x = x;
         this.y = y;
     }

     // hashcode and equals methods
     // getters and utility methods

}

关于java - 当我向 java HashSet 添加一个元素时,所有元素都会发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29008922/

相关文章:

java - "GetObjectClass"方法和"FindClass"方法区别及用法

java - Guava 的 ImmutableSet 成员方法是否模仿 java.util.HashSet#contains?

.net - 克隆 HashSet<T> 的有效方法?

java - 在 HashSet 的 ArrayList 中重新创建 HashSet

Java 在给定枚举值的情况下获取枚举名称

java - Struts2 <filter> 和 <filter-mapping> 导致错误

Java:我打算仅覆盖的库方法的 protected 或公共(public)访问?

java - 制作一个 Hashmap,其键是字符串,值是 HashSets

c# - 依赖于未修改的 HashSet 的迭代顺序

java - "While"和 "do while"验证 "for"循环