HashMap.containsKey(key) 找不到密钥,使用自定义 class 作为密钥类型

HashMap.containsKey(key) failing to find key, with custom class used as key type

TL;DR:我用我自己的 "Pair" class 对象创建了一个 hashmap 对象用作键。当我使用 hashmap.containsKey(Pair) 时,找不到密钥。

我有一个名为 Pair 的 class,代码如下所示。它应该是两个物体的容器。第一个对象可以是任何类型,而第二个对象必须是整数。这不是很好的设计,但我以这种方式编码,因此我可以在我的程序中将 class 用于其他目的。

import java.util.ArrayList;

public class Pair<L> {
    private L left;
    private int right;

    public Pair(L left, int right) {
        this.left = left;
        this.right = right;
    }

    public L getLeft() { return left; }
    public int getRight() { return right; }

    public void ToString() {
        System.out.println(left + "," + right);
    }

    public boolean equals(Pair p) {
        return (this.getLeft().equals(p.getLeft()) && this.getRight() == p.getRight());
    }

    public ArrayList<Pair> neighbors(int rowLimit, int ColumnLimit) {
        ArrayList<Pair> neighbors = new ArrayList<Pair>();
        Pair neighborL;
        Pair neighborR;
        Pair neighborU;
        Pair neighborD;
        if (((int)this.left-1 >= 0)) {
            neighborU = new Pair((int)this.left-1, this.right);
//          neighborU.ToString();
            neighbors.add(neighborU);
        }
        if ((int)this.left+1 < rowLimit) {
            neighborD = new Pair((int)this.left+1, this.right);
//          neighborD.ToString();
            neighbors.add(neighborD);
        }
        if ((int)this.right-1 >= 0) {
            neighborL = new Pair((int)this.left, this.right-1);
//          neighborL.ToString();
            neighbors.add(neighborL);
        }
        if ((int)this.right+1 < ColumnLimit) {
            neighborR = new Pair((int)this.left, this.right+1);
//          neighborR.ToString();
            neighbors.add(neighborR);
        }
        return neighbors;
    }
}

我将 Pairs 作为键存储在哈希图中,如下所示:

Map<Pair, Integer> costSoFar = new HashMap<Pair, Integer>();
costSoFar.put(sLocale, 0);

当我运行下面一行,也就是说,如果key不在hashmap中:

if (!costSoFar.containsKey(next))

它的计算结果为真,即使我知道密钥就在那里,正如我通过调试检查的那样。

如果有人能帮助弄清楚散列图无法识别密钥的原因,我们将不胜感激。也许我的 equals 方法不符合要求?

如果 L 看起来也是 int,为什么还要使用泛型?

替换你的等号:

public boolean equals(Object o) {
    if (o instanceof Pair){
         Pair p = (Pair)o;
         return (this.getLeft().equals(p.getLeft()) && this.getRight() == p.getRight());
    }
    return false;
}

并实施 int hashCode():

public int hashCode() {
    return this.getLeft() * 31 + this.getRight();
}

java.util.HashMap中的方法containsKey(Object)使用调用hashCode()java.util.HashMap.getEntry(Object)获取Key的hashCode并用它来检索对象。您需要覆盖 java.lang.Object.hashCode() 以使您的代码正常工作。