使用自定义 Pair 对象作为键访问 HashMap 值

Accessing a HashMap value with a custom Pair Object as a key

我是 Java 的新手。我正在写一个 2d 游戏,我决定使用 HashMap 来存储我的地图数据,因为我需要支持我的地图坐标的负索引。这是因为地图的大小可以在游戏过程中变大。

我写了一个自定义对 class 来存储最终的 x 和 y 值。我正在使用这个 Pair 对象作为我的 HashMap 的键。我的值是自定义 Cell class.

的实例

我已经声明了我的 HashMap 如下:

HashMap<Pair, Cell> tiles = new HashMap<Pair, Cell>();

接下来,我使用以下方法将条目添加到我的地图:

tiles.put(new Pair(0,0), new Cell());

0,0 显然是这个单元格的唯一 x,y 坐标。

如何使用特定于单个 Pair 的 HashMap 的 .get() 方法访问 Cell 的字段和方法?例如 Pair(0,0) 或 Pair(0,1)。如果密钥只是一个字符串或一个整数,我就没有问题。我只是不知道如何为具有特定坐标的对象格式化我的密钥。

你只需写 tiles.get(new Pair(0, 0)),就像你写 put 一样。

您需要覆盖 hashCode()。类似于:

public int hashCode() {
    return 17 * this.key + 31 * this.value;
}

您需要覆盖 Pair class 的 equalshashCode 方法。现在,如果您有两个 Pair 实例:

Pair p1 = new Pair(0,0);
Pair p2 = new Pair(0,0);

你程序中的这两个实例不会被视为相等,因此如果你说:

tiles.put(p1, XXX);
tiles.put(p2, YYY);

这种行为会使您的地图具有两个不同的键和两个不同的值 - 我相信您想要的是一个键,在这些语句执行后最后一个值为 YYY。

实现 hashCodeequals 后,您可以编写一个静态辅助方法,用一些给定的坐标实例化一个新的 Pair,并执行地图查找:

static Cell lookup(int x, int y) {
    return tiles.get(new Pair(x, y));
}

这是帮助您入门的基本配对 class:

public class Pair {

    private final int x;
    private final int y;

    public Pair(final int x, final int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof Pair)) {
            return false;
        }

        final Pair pair = (Pair) o;

        if (x != pair.x) {
            return false;
        }
        if (y != pair.y) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }
}

您需要为您的 Pair() 类型覆盖方法 .equals().hashCode()。需要它们才能在 HashMap 中使用类型。等于可以检查 2 个值是否相等:

@Override public boolean equals(Object o) {
    if(this == o) return true;
    if(!(o instanceof Pair)) return false;
    Pair p = (Pair)o;
    return p.x == x && p.y == y;
}

对于 hashCode,您必须生成一个唯一的值:

private volatile int hashCode; // define this as a member of the class

@Override public int hashCode() {
    int result = hashCode;
    if(result == 0) {
        result = 17 * x + 31 * y;
        hashCode = result;
    }
    return result;
}

然后您可以通过简单地调用

访问位于 (0, 0) 的单元格
tiles.get(new Pair(0, 0));