Reputation: 97
In a Conway's game of life simulator, I have eight blocks of code that look like this to find the neighborhood of a cell.
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 is the point representing the current cell, data is a HashSet containing the active cells. For the sake of efficiency I'm only checking dead cells that neighbor live cells, so deadCellsToCheck is another HashSet that starts each generation empty. Each time I execute deadCellsToCheck.add(p), it seems like all the cells already in it get overwritten to be the cell just added, because the output looks like this:
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...
I don't think this should be possible for multiple reasons. Any ideas?
Upvotes: 0
Views: 1444
Reputation: 5578
The reason of this problem is that your HashSet
contains the same instance of Point
multiple times. Instead of editing the point p.setLocation(p.x-1, p.y-1);
you should be creating a new one and adding it to the set:
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();
}
Your current structure also violates contract of hashCode()
method:
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
The hashCode
and equals
methods are used by the set to eliminate duplications. You create point (0,0)
which has hashcode = 0
. Then you modify the point to (1,0)
, its haschode changes to 1072693248
so the set allows to insert this point again. But it is the same instance - it is the same object inserted twice into the set.
Mutable objects generally shouldn't be used in sets or other data structures relying on hashcode
method.
The solution is to make the point immutable (if you use java.awt.Point
, I would recommend to create your own class):
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
}
Upvotes: 6
Reputation: 59112
It looks like you are adding one point to the set over and over again, and altering its value. If you want to add a bunch of different points, you need to make a bunch of new point objects (use the word new
) instead of just one.
Upvotes: 1