作者:忧伤丿稻草展 | 来源:互联网 | 2023-05-18 12:38
在康威的生命游戏模拟器中,我有八个代码块,看起来像这样找到一个单元格的邻域.
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是包含活动单元格的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...
我不认为这可能有多种原因.有任何想法吗?
1> Jaroslaw Paw..:
出现此问题的原因是您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()
方法合同:
每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数
该hashCode
和equals
方法使用的一套以消除重复.你创造了(0,0)
具有的点hashcode = 0
.然后将点修改为(1,0)
,其haschode更改为,1072693248
因此set允许再次插入此点.但它是相同的实例 - 它是在集合中插入两次的相同对象.
可变对象通常不应该依赖于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
}