我有一个程序,该程序首先生成一个Hashmap,并将特定对象(称为BoardState)的所有允许实例作为键。然后,我遍历键集,创建BoardState对象的副本并对其进行转换,然后在状态图中查找转换后的对象并更新其关联值。问题是,当我在此键集上使用contains()方法(直接或通过首先创建键的HashSet)时,即使该对象确实存在于映射中,它有时也会为我的新对象返回false。
我知道明显的答案是,我在BoardState或其某个字段中的equals()或hashcode()的实现存在问题,我倾向于同意。实际上,我已经能够将问题缩小一些。 BoardState包括一个Box对象的HashSet作为实例变量,我也实现了它,并且设置Box的hashcode()方法以返回常量可以解决该问题(尽管这显然不是可接受的解决方案)。
问题是,当我遇到错误时,我仍然可以遍历键集并通过使用equals()比较来找到对象。如果然后我输出该对象的哈希码和要检查的对象的哈希码,则对于每个对象我都得到相同的结果,所以我对为什么contains()引发错误感到困惑。
如果下面的代码有点笨拙,我深表歉意,我试图去掉我能做的,而仅显示与错误有关的内容。
public class BoardState {
private static int size;
private static int totalTokens;
private static HashMap<Colour, Integer> colours;
private static HashSet<Token> fullTokenSet;
private int inactiveBoxes;
private HashSet<Box> boxes;
private HashSet<Token> offBoardTokens;
public BoardState(...){...}
public boolean checkRemoveBox(final Box box,
final HashMap<BoardState, Boolean> stateMap) {
BoardState checkState = copy();
checkState.remove(box, box.getBoxColours());
if (!stateMap.keySet().contains(checkState)) {
for (BoardState state : stateMap.keySet()) {
if (state.equals(checkState)){
System.out.println("state hashcode: " + Objects.hash(state));
System.out.println("checkstate hashcode: " +
Objects.hash(checkState));
}
}
throw new IllegalStateException ("State not found.");
} else {
if (!stateMap.get(checkState)) {
return false;
}
}
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BoardState state = (BoardState) o;
return size == state.size &&
inactiveBoxes == state.inactiveBoxes &&
totalTokens == state.totalTokens &&
boxes.equals(state.boxes) &&
fullTokenSet.equals(state.fullTokenSet) &&
offBoardTokens.equals(state.offBoardTokens) &&
colours.equals(state.colours);
}
@Override
public int hashCode() {
return Objects.hash(inactiveBoxes, boxes, offBoardTokens);
}
}
public class Box {
private static int totalTokens;
private HashSet<Token> tokens;
Box(...) {...}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Box box = (Box) o;
return totalTokens == box.totalTokens &&
Objects.equals(tokens, box.tokens);
}
@Override
public int hashCode() {
return tokens.hashCode();
}
}
给定的代码给出以下输出:
state hashcode: 157760
checkstate hashcode: 157760
Exception in thread "main" java.lang.IllegalStateException: State not found.
at game.BoardState.checkSplitBox(BoardState.java:306)
at game.BoardState.checkSplit(BoardState.java:284)
at game.Game.checkForP1Win(Game.java:173)
at game.Main.main(Main.java:11)
Process finished with exit code 1