Java HashSet似乎没有意识到两个对象是相同的。
我试图使用HashSet来存储我创建的类的对象,但是显然相同的对象似乎有两个不同的哈希,这就是为什么contains方法没有意识到对象已经在HashSet中。这导致我的程序堆内存不足 我不认为我做错了什么,但我还是想听听别人的意见。我以前做过类似的手术,所有的手术都很好,这让我特别恼火。我非常感谢你的帮助 这是我的密码Java HashSet似乎没有意识到两个对象是相同的。,java,hashset,Java,Hashset,我试图使用HashSet来存储我创建的类的对象,但是显然相同的对象似乎有两个不同的哈希,这就是为什么contains方法没有意识到对象已经在HashSet中。这导致我的程序堆内存不足 我不认为我做错了什么,但我还是想听听别人的意见。我以前做过类似的手术,所有的手术都很好,这让我特别恼火。我非常感谢你的帮助 这是我的密码 move1 = new Move(t,s); if(move1.hashCode()==new Move(t,s).hashCode()) System.out.prin
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");
下面是移动类:
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.<init>(makeMove.java:33)
线程“main”java.lang.OutOfMemoryError中的异常:java堆空间
在java.util.HashMap.addEntry(HashMap.java:797)
位于java.util.HashMap.put(HashMap.java:431)
在java.util.HashSet.add处(HashSet.java:194)
在makeMove。(makeMove.java:33)
HashSet将根据调用hashCode()和equals()来确定相等性。您尚未实现这些,所以将从对象继承它们。对象的hashCode和equals方法只是基于引用是否相等 这就是为什么
if(move1.hashCode()==newmove(t,s.hashCode())
为false。move1与通过调用new Move(t,s)创建的实例不同
您需要在Move类中实现hashCode和equals
e、 g.(虽然可能不是最优的,而且您可能需要一个空安全的equals——如果可以的话,让您的IDE生成它们)
您需要重写Move
类中的方法,让它为Move
实例的状态返回相同的hashCode()
值。也不要忘记覆盖
另见:
提示:如果您使用的是类似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;
}
您必须重写
equals()
和hashCode()
这可能是一种选择
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)
有关更多信息:
谢谢你的提醒。特别是对于Eclipse技巧,这些都记录在JavadocforHashset中。这就是它的目的!明亮的工作完美无瑕。非常感谢。重新标记,因为异常是问题的副作用。您的哈希代码不太正确。你不应该把这两个数字都乘以31再加上。您应该将move1乘以31,然后将结果乘以31,再加上move2。@EngledLoops错了,绝对不需要遵循任何特定的算法来创建哈希代码(请参阅)。您所描述的更流行的方式与结果的正确性完全无关。您可以使用任何其他号码以及任何其他操作和订单,只要符合上述规范。我知道你是从哪里来的,但这与说我的示例“不太正确”和“我不应该这样做”之间有区别。根据这种逻辑,让所有的
hashCode()
函数返回1是正确的。当然,你可以做你想做的事情,但这是一个原因,它通常是在考虑一个特定的策略的情况下完成的:因为它提供了更多不同的bucketing,这是散列的首要目的。您的代码示例使两个数字都是31的倍数,这意味着它们的总和也是31的倍数,这可能会导致每个项目散列到同一个bucket中。
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() );
}
}