HashMap获取“相等”但不同哈希的对象的值?

时间:2013-01-29 18:44:38

标签: java

我有一个HashMap<Point, T>数据结构,它包含几个映射到类T的其他实例的点。当我的类被实例化时,这个映射给出了一些默认值:

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

在我的代码中,我将接收包含xy值的事件。当我收到其中一个事件时,我正在尝试使用传递的Pointx创建一个新的y对象,然后像这样从地图中检索值:

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

虽然在这种情况下p等于p1(使用(x,y)=(0,1)我从{{1}返回null值我认为这是因为map中的hashCode()方法使用了Point (Point2D)之外的其他方法来计算唯一的哈希,它应该防止冲突。

我的问题是:如何使用新实例equalsmap中检索值?是否有其他适合用例的数据结构?

我想我可以使用p或其他一些映射,例如toString(),或者我可以扩展HashMap<String, T>类和Point Override方法以适应我的目的。但是,如果有一种更清洁的方式我会喜欢听到它,这些方式会感到“hacky”。​​

4 个答案:

答案 0 :(得分:5)

根据Java documentation

  

如果两个对象根据equals(Object)方法相等,则在两个对象中的每一个上调用hashCode方法必须产生相同的整数结果。

在您的情况下,似乎两个Point个对象相等(根据equals方法),但它们的哈希码是不同的。这意味着您需要修复equalshashCode函数,使其保持一致。

答案 1 :(得分:2)

您可以尝试编写一个自包含的示例,例如我们可以运行的

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

打印

0 mis-matches found.

答案 2 :(得分:2)

我认为Point类的equals()或hashcode()没有任何问题。试试这个:

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



    }

它产生了正确的结果。

我猜你没有正确地初始化地图。

答案 3 :(得分:1)

hashCode()应使用与equals()相同的属性,以保持一致。

另请参阅:What issues should be considered when overriding equals and hashCode in Java?