Reputation: 359
I'm trying to store multiple values for a key in a data structure so I'm using Guava (Google Collection)'s MultiMap.
Multimap<double[], double[]> destinations = HashMultimap.create();
destinations = ArrayListMultimap.create();
double[] startingPoint = new double[] {1.0, 2.0};
double[] end = new double[] {3.0, 4.0};
destinations.put(startingPoint, end);
System.out.println(destinations.containsKey(startingPoint));
and it returns false.
Note: Key-values are being stored in the multimap as the destinations.size()
increases when I put something there.It also does not happen when keys are String
instead of double[]
.
Any idea what the problem is?
Edit: Many thanks to Jon Skeet I now implemented the class:
class Point {
double lat;
double lng;
public boolean equals(Point p) {
if (lat == p.lat && lng == p.lng)
return true;
else
return false;
}
@Override
public int hashCode() {
int hash = 29;
hash = hash*41 + (int)(lat * 100000);
hash = hash*41 + (int)(lng * 100000);
return hash;
}
public Point(double newlat, double newlng) {
lat = newlat;
lng = newlng;
}
}
And now I have a new problem. This is how I'm using it:
Multimap<Point, Point> destinations = HashMultimap.create();
destinations = ArrayListMultimap.create();
Point startingPoint = new Point(1.0, 2.0);
Point end = new Point(3.0, 4.0);
destinations.put(startingPoint, end);
System.out.println( destinations.containsKey(startingPoint) );
System.out.println( destinations.containsKey(new Point(1.0, 2.0)) );
The first one returns true, the second one returns false. It gives me an error if I put @Override
before the equals
method.Any Idea what the problem is now?
Thanks :)
Edit2: It now behaves exactly as expected when I changed equals
to this:
@Override
public boolean equals(Object p) {
if (this == p)
return true;
else if ( !(p instanceof Point) )
return false;
else {
Point that = (Point) p;
return (that.lat == lat) && (that.lng == lng);
}
}
Thanks everyone.
Upvotes: 2
Views: 1023
Reputation: 1501916
You're using arrays as the hash keys. That's not going to work - Java doesn't override hashCode
and equals
for arrays. (The Arrays
class provides methods to do this, but it's not going to help you here.) Admittedly I'd expect it to work in this specific case, where you're using the exact same reference for both put
and containsKey
... When I test your code, it prints true
. Are you sure you can reproduce it with exactly your code?
For example, while I'd expect it to work for the code you've given, I wouldn't expect this to work:
// Logically equal array, but distinct objects
double[] key = (double[]) startingPoint.clone();
System.out.println(destinations.containsKey(key));
It sounds like you shouldn't really be using double[]
here - you should create a Point
class which has two double
variables, and overrides equals
and hashCode
.
Additionally, using double
values in hash keys is usually a bad idea anyway, due to the nature of binary floating point arithmetic. That's going to be a problem even using the Point
idea above... it should be okay if you don't need to actually do any arithmetic (if you're just copying values around) but take great care...
Upvotes: 8
Reputation: 5173
The problem is that you cannot hash "equal" arrays and get the same result each time. For example:
public static void main(String[] args) {
System.out.println(new double[]{1.0, 2.0}.hashCode());
System.out.println(new double[]{1.0, 2.0}.hashCode());
}
will result something like
306344348
1211154977
Upvotes: 1