Does a HashMap get the value of an equal object, but is different from a hash?

I have a HashMap<Point, T> data structure that contains several points that are mapped to other instances of class T This map has some default values ​​when an instance of my class is created, for example:

 T t1 = new T(); T t2 = new T(); Point p1 = new Point(0, 1); Point p2 = new Point(0, 2); HashMap<Point, T> map = new HashMap<Point, T>(); static { map.put(p1, t1); map.put(p2, t2); } 

In my code, I will receive events containing the value of x and y . When I receive one of these events, I try to create a new Point object with missing x and y , and then extract the value from the map as follows:

 Point p = new Point(event.getX(), event.getY); // Assume (x, y) = (0, 1) (p1) if(p.equals(p1) T t = map.get(p); 

Although in this case p is equal to p1 (with (x, y) = (0, 1), I get the null value from map . I assume that this is because the hashCode() method in Point (Point2D) uses something other than equals to compute a unique hash that should prevent collisions.

My question is: how can I get the value from map using a new instance of p ? Is there any other data structure that matches the usage scenario?

I think I could use toString() or some other mapping, for example HashMap<String, T> , or maybe I would extend the Point and Override class to hashCode() method in accordance with my goals. These methods feel β€œhacked”, although if there is a cleaner way, I would like to hear it.

+6
source share
4 answers

According to the Java documentation,

If two objects are equal in accordance with the equals(Object) method, then calling the hashCode method for each of the two objects should lead to the same integer result.

It looks like in your case the two Point objects are equal (using the equals method), but their hash codes are different. This means that you need to fix your equals and hashCode functions so that they are consistent with each other.

+5
source

Can you try writing a standalone example, for example, following how we can run

 Map<Point, String> map = new LinkedHashMap<>(); for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) map.put(new Point(i, j), "(" + i + "," + j + ")"); // test the map int misMatches = 0; for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) { String expected = "(" + i + "," + j + ")"; String text = map.get(new Point(i, j)); if (!expected.equals(text)) { System.err.println("Expected <" + expected + "> but got <" + text + ">"); misMatches++; } } System.out.println(misMatches + " mis-matches found."); 

prints

 0 mis-matches found. 
+2
source

I do not think there is a problem with equals () or hashcode () of the Point class. Try the following:

 public static void main(String args[]) { Map<Point, Integer> map = new HashMap<Point, Integer>(); Point p1 = new Point(0, 1); Point p2 = new Point(0, 2); map.put(p1,1); map.put(p2,2); Point p = new Point(0, 1); if(p.equals(p1)){ System.out.println(map.get(p)); } else{ System.out.println("not"); } } 

It produces the correct result.

I assume that you are not initializing the map correctly.

+2
source

hashCode () must use the same attributes as equals () to be consistent.

See also: What issues should be considered when overriding equals and hashCode in Java?

+1
source

All Articles