Java 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

我试图使用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");
下面是移动类:

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()  );
    }
}