【问题标题】:Java MultiMap Not Recognizing KeyJava MultiMap 无法识别密钥
【发布时间】:2012-04-05 12:47:37
【问题描述】:

我正在尝试为数据结构中的键存储多个值,因此我使用 Guava (Google Collection) 的 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。

注意:当我将某些内容放在那里时,键值将存储在多映射中,因为 destinations.size() 会增加。当键是 String 而不是 double[] 时,也不会发生这种情况。

知道问题出在哪里吗?

编辑:非常感谢 Jon Skeet 我现在实现了这个类:

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。如果我将@Override 放在equals 方法之前,它会给我一个错误。知道现在的问题是什么吗?

谢谢:)

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

谢谢大家。

【问题讨论】:

标签: java hashmap multimap


【解决方案1】:

您使用 arrays 作为哈希键。那是行不通的——Java 不会覆盖数组的hashCodeequals。 (Arrays 类提供了执行此操作的方法,但在这里对您没有帮助。)诚然,我希望它在这种特定情况下工作,您使用的是 完全相同的参考 对于putcontainsKey...当我测试你的代码时,它会打印true。你确定你可以用 exactly 你的代码重现它吗?

例如,虽然我希望它适用于您提供的代码,但我不会希望它会起作用:

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

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

此外,由于二进制浮点运算的性质,在哈希键中使用double通常无论如何都是个坏主意。即使使用上面的Point 想法,这也会成为一个问题......如果您实际上不需要进行任何算术运算(如果您只是复制值)应该没问题,但要非常小心......

【讨论】:

  • @Tring:我从来没有建议过。请参阅我的编辑以获取替代方案。
  • 我实现了你的建议,但我仍然有一个小问题。你能看看吗?
  • @Tring:你还没有覆盖 equals(Object) - 你已经用 equals(Point) 重载了它,它没有被调用......
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 2013-09-12
    • 2016-10-28
    • 1970-01-01
    相关资源
    最近更新 更多