2012-04-05 69 views
2

我试图在数据结构中存储一个密钥的多个值,所以我使用的是Guava(Google集合)的MultiMap。Java 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)); 

它返回false。

注意:键值存储在multimap中,因为destinations.size()在我放置某些东西时增加。当键为String而不是double[]时,也不会发生键值。

任何想法是什么问题?

编辑:非常感谢乔恩斯基特我现在实现的类:

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; 
    } 
} 

而且现在我有一个新的问题。这是我如何使用它:

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))); 

第一个返回true,第二个返回false。它给了我一个错误,如果我把@Overrideequals方法之前。任何想法现在是什么问题?

谢谢:)

EDIT2:现在的行为完全如预期,当我改变equals这样:

@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); 
    } 
} 

谢谢大家。

+0

有一个[相关问题](http://stackoverflow.com/questions/16839182/can-a-java-array-be- used-as-a-hashmap-key)用于普通Java“Map”情况。 – Raedwald 2015-02-26 12:57:39

回答

8

您正在使用阵列作为散列键。这不起作用 - Java不会覆盖数组的hashCodeequals。 (Arrays类提供了这样做的方法,但它不会帮你在这里。)不出所料,我希望它在这种特定情况下工作,其中你使用完全相同的参考putcontainsKey。 ..当我测试你的代码时,它打印true。你确定你可以用正确你的代码重现吗?

例如,虽然我希望它为你提供了代码工作,我不会想到这个工作:

// Logically equal array, but distinct objects 
double[] key = (double[]) startingPoint.clone(); 
System.out.println(destinations.containsKey(key)); 

这听起来像你真不该使用double[]在这里 - 你应该创建一个Point类有两个double变量,并覆盖equalshashCode

此外,使用double散列键值是通常无论如何,由于二进制浮点运算的本质,无论如何。这是怎么回事,即使使用上述Point想法是一个问题......它应该是好的,如果你不需要实际做任何运算(如果你只是复制周围值),但会非常谨慎......

+1

@Tring:我从来没有这样说过。看到我的编辑替代。 – 2012-04-05 12:57:03

+0

谢谢...明白了:) – Tring 2012-04-05 13:00:20

+0

我实施了你的建议,并且还有一个小问题。你能看看吗? – Tring 2012-04-05 13:51:27

1

问题是你不能散列“平等”的数组,每次都得到相同的结果。例如:

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()); 
} 

会导致类似

306344348 
1211154977