我目前正在使用地图编辑器开发TD游戏。显然,你可以保存并加载这些地图(或者至少应该能够)。
问题是:在某个时刻,我在.get()
上呼叫HashMap
。不幸的是,应该是相同的(逻辑方面的)键不是相同的对象(就参考而言),并且,根据我以前的谷歌研究,覆盖他们的.equals
方法是不够的,因为他们仍然会使用.hashCode()
返回不同的哈希值(我验证过,他们会返回不同的哈希值,而.equals
确实返回true)。
(另一方面,由于HashMap.get(key)
的javadoc只表明它们必须相等,因此相当令人困惑)
更具体地说,HashMap
包含我的类Path
的实例作为键,并且应该返回相应的敌人列表(= value)。
Path
的简短版本(没有getter等):
public class Path
{
private List<Tile> tiles = new ArrayList<>();
@Override
public boolean equals(Object obj) {
//code comparing the two paths
}
@Override
public int hashCode() {
//what I still need to implement. ATM, it returns super.hashCode()
}
}
public class Tile
{
private int x;
private int y;
//constructor
//overrides equals
//getters & some convenience methods
}
现在如果两个Path相等,我希望它们返回相同的哈希码,以便HashMap
返回正确的敌人列表。 (我确保不能添加两个相同的路径)。
现在我的问题:
你建议
请注意,我更愿意避免将HashMap
更改为其他类型的地图,如果这样可以帮助解决问题。
答案 0 :(得分:2)
您肯定需要实施与hashCode
一致的equals
。 IDE通常可以正常生成hashCode
和equals
。另请考虑Objects.equals(...)
和Objects.hash(...)
。
关于在Path
中使用HashMap
作为键的一个警告。您必须使该类不可变,以使其可靠地工作。或者至少确保密钥的hashCode
不会改变。否则,即使使用相同或相同的密钥,您也可能无法获得数据。
答案 1 :(得分:1)
List
有一个有用的方法,方便地命名为list.hashCode()
。这将计算列表中所有元素的hashCode。所以你还必须为Tile
实现hashCode,它可能包含一些原始字段等。
e.g。
@Override
public int hashCode() {
return tiles != null ? tiles.hashCode() : 0;
}
查看文档here
int hashCode()
返回此列表的哈希码值。列表的哈希码被定义为以下计算的结果:
int hashCode = 1;
for (E e : list)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
根据
list1.equals(list2)
的一般合同的要求,这可确保list1.hashCode()==list2.hashCode()
隐含任意两个列表list1
和list2
Object.hashCode()
。