尽管可以通过迭代和使用equals()且哈希码相同,但get()和contains()方法在HashSet中找不到对象,

时间:2019-08-08 14:34:34

标签: java hashmap contains hashset hashcode

我有一个程序,该程序首先生成一个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

0 个答案:

没有答案