HashSet似乎没有意识到两个对象是相同的。

我正在尝试使用HashSet来存储我创建的类的对象,但显然相同的对象似乎有两个不同的哈希值,这就是为什么contains方法没有意识到该对象已经在HashSet中。 这导致我的程序耗尽堆内存。

我不认为我做错了什么,但无论如何我想要第二意见。 我做过类似的操作,之前一切正常,这使得这特别烦人。 我很感激任何帮助。

这是我的代码

move1 = new Move(t,s); if(move1.hashCode()==new Move(t,s).hashCode()) System.out.println("match"); move2 = new Move(s,t); moves.add(move1); moves.add(move2); if(moves.contains(new Move(t,s))) System.out.println("match found"); 

这是Move类:

 public class Move { private int move1; private int move2; Move(int m1, int m2) { move1 = m1; move2 = m2; } public String toString() { return String.valueOf(move1)+" "+String.valueOf(move2); } } 

这是我得到的输出

 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.HashMap.addEntry(HashMap.java:797) at java.util.HashMap.put(HashMap.java:431) at java.util.HashSet.add(HashSet.java:194) at makeMove.(makeMove.java:33) 

您需要覆盖Move类中的Object#hashCode()方法,以使其返回Move实例状态的相同hashCode()值。 不要忘记重写Object#equals()

也可以看看:

  • 在Java中覆盖equals和hashCode

提示 :如果你使用像Eclipse这样的IDE,你也可以自动生成它们。 右键单击Move类,选择Source> Generate hashCode()和equals() 。 这是它的样子:

 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + move1; result = prime * result + move2; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Move other = (Move) obj; if (move1 != other.move1) return false; if (move2 != other.move2) return false; return true; } 

HashSet将基于调用hashCode()和equals()来确定相等性。 您尚未实现这些,因此您将从Objectinheritance它们。 Object的hashCode和equals方法仅基于引用是否相等。

这就是为什么if(move1.hashCode()==new Move(t,s).hashCode())为false。 move1是一个不同于通过调用new Move(t,s).hashCode()创建的实例的实例。

您需要在Move类中实现hashCode和equals。

例如(虽然可能是非最优的,你可能想要一个null安全等于 – 如果可以,你的IDE会生成它们)

 public int hashCode() { return move1 ^ move2 +; } public boolean equals(Object o) { if(!other instanceof Move) return false; Move other = (Move)o; return other.move1 == move1 && other.move2 == move2; } 

你必须覆盖equals()和hasCode()

这可能是一种选择。

 import static java.lang.System.out; public class Move { private int move1; private int move2; Move(int m1, int m2) { move1 = m1; move2 = m2; } public String toString() { return String.valueOf(move1)+" "+String.valueOf(move2); } public int hashCode() { return move1 * 31 + move2 * 31; } public boolean equals( Object other ) { if( this == other ) { return true; } if( other instanceof Move ) { Move m2 = ( Move ) other; return this.move1 == m2.move1 && this.move2 == m2.move2; } return false; } public static void main( String [] args ) { out.println( new Move(2,3).equals( new Move(2,3))); out.println( new Move(1,1).hashCode() == new Move(1,1).hashCode() ); } } 

您必须定义移动的顺序是否相关(1,2等于2,1或不是)

了解更多信息:

在Java中覆盖equals和hashCode时应该考虑哪些问题?

第8项:当你覆盖equals from:“Effective Java” http://bit.ly/cd7uUl时,总是覆盖hashCode