tkroman
tkroman

Reputation: 4798

How to make my HashMap work as expected?

Suppose one has a simple class:

public class Point implements Comparable<Point> {

    public int compareTo(Point p) {
        if ((p.x == this.x) && (p.y == this.y)) {
            return 0;
        } else if (((p.x == this.x) && (p.y > this.y)) || p.x > this.x) {
            return 1;
        } else {
            return -1;
        }
    }

    private int x;
    private int y;

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

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

And a HashMap from Point to something, let's say Cell: cellMap = new HashMap<Point, Cell>(); Then one fills in cellMap as follows:

for (int x = -width; x <= width; x++) {
    for (int y = -height; y <= height; y++) {
        final Point pt = new Point(x,y);
        cellMap.put(pt, new Cell());
        }
    }
}

And then one does something like (trivial) this:

for (Point pt : cellMap.keySet()) {
            System.out.println(cellMap.containsKey(pt));
            Point p = new Point(pt.getX(), pt.getY());
            System.out.println(cellMap.containsKey(p));
}

And gets true and false in, respectively, first and second cases. What is going on? Is this map comparing hashes instead of values? How to make the example return true in both cases?

Upvotes: 1

Views: 121

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727047

Since you are using HashMap, not TreeMap, you need to override hashCode and equals, not compareTo, in your Point class:

@Override
public int hashCode() {
    return 31*x + y;
}
@Override
public bool equals(Object other) {
    if (other == null) return false;
    if (other == this) return true;
    if (!(other instanceof Point)) return false;
    Point p = (Point)other;
    return x == p.x && y == p.y;
}

Upvotes: 8

Related Questions