1

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?

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
tkroman
  • 4,811
  • 1
  • 26
  • 46
  • possible duplicate of [Why do I need to override the equals and hashCode methods in Java?](http://stackoverflow.com/questions/2265503/why-do-i-need-to-override-the-equals-and-hashcode-methods-in-java) – user2864740 May 19 '14 at 21:32

1 Answers1

8

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;
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Thank you. Another question: if I override `hashCode` to return the same hash for points with equal coordinates, I won't have ability (let's suppose I DO need it) to distinguish `p1 = new Point(0, 0)` and `p2 = new Point(0, 0)`? – tkroman Jul 01 '13 at 18:46
  • @cdshines You can always distinguish between two instances representing equivalent objects using reference equality `==`. You can even use them in an `InstanceHashMap` (which is not a proper hash map, because it does not follow the same contract). – Sergey Kalinichenko Jul 01 '13 at 18:48