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

发布于 2024-09-18 17:05:06 字数 1059 浏览 2 评论 0 原文

我试图使用 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.<init>(makeMove.java:33)

I'm trying to use HashSet to store objects of a class that I created, but apparently the same objects seem to have two different hashes, which is why the contains method does not realize that the object is already in the HashSet. This leads to my program running out of heap memory.

I don't think I'm doing anything wrong, but I wanted a second opinion anyway. I've done similar operations before which all worked fine, which makes this particularly annoying. I'd appreciate any help.

Here's my code

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");

Here's the Move class:

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

Here's the output I get

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

遥远的她 2024-09-25 17:05:07

HashSet 将根据调用 hashCode() 和 equals() 来确定相等性。您尚未实现这些,因此您将从 Object 继承它们。 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;
}

HashSet will determine equality based on calling hashCode() and equals(). You have not implemented these, so you'll inherite them from Object. The hashCode and equals methods of Object is just based on whether the references are equal.

That's why if(move1.hashCode()==new Move(t,s).hashCode()) is false. move1 is a different instance than the instance created by calling new Move(t,s).hashCode()

You'll need to implement hashCode and equals in your Move class.

e.g.(though perhaps non-optimal, and you might want a null safe equals - have your IDE generate them if it can)

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;
}
空‖城人不在 2024-09-25 17:05:07

您必须重写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 )

有关详细信息:

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

You have to override equals() and hashCode().

This may be an option.

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

You have to define if the order of the move is relevant ( 1,2 isequals to 2,1 or not )

For more information:

What issues should be considered when overriding equals and hashCode in Java?

メ斷腸人バ 2024-09-25 17:05:06

您需要覆盖 Move 类中的 >Object#hashCode() 方法,使其返回与 状态相同的 hashCode() 值>移动实例。不要忘记覆盖 Object#equals() 也是如此。

另请参阅:


提示:如果您使用的是 Eclipse 之类的 IDE,您也可以自动生成它们。右键单击 Move 类的某处,选择Source >生成 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;
}

You need to override the Object#hashCode() method in the Move class to let it return the same hashCode() value for the state of the Move instance. Don't forget to override Object#equals() as well.

See also:


Hint: if you're using an IDE like Eclipse, you can also just autogenerate them. Rightclick somewhere the Move class, choose Source > Generate hashCode() and equals(). Here is how it look like then:

@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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文