在康威的生命游戏模拟器中,我有八个代码块,看起来像这样找到一个单元格的邻域.
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();
}
Run Code Online (Sandbox Code Playgroud)
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...
Run Code Online (Sandbox Code Playgroud)
我不认为这可能有多种原因.有任何想法吗?
出现此问题的原因是您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();
}
Run Code Online (Sandbox Code Playgroud)
您当前的结构也违反了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
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
448 次 |
| 最近记录: |