1

我正在尝试创建一个搜索算法,将坐标对存储在一个名为 HashSquareSpec 的包装类中。为了避免重复并保持插入顺序,我将每个 HashSquareSpec 插入到 LinkedHashSet 中。即使我重写了 equals() 方法和 hashCode() 方法,LinkedHashSet 仍然接受具有相同坐标对的两个 HashSquareSpec 对象。

public static void main(String [] args)
{
    LinkedHashSet<HashSquareSpec> firedShots = new HashLinkedSet<HashSquareSpec>();
    HashSquareSpec a = new HashSquareSpec(1,2);
    HashSquareSpec b = new HashSquareSpec(2,2);
    HashSquareSpec c = new HashSquareSpec(1,2);
    HashSquareSpec d = new HashSquareSpec(3,2);

    firedShots.add(a);
    firedShots.add(b);
    firedShots.add(c);
    firedShots.add(d);
    System.out.println(a.equals((SquareSpec)c));
    Iterator l = firedShots.iterator();
    while(l.hasNext())
    {
        System.out.println(l.next().hashCode());
    }
}

Output:
true
38444474
38474265
38444474
38504056

HashSquare 类

public class HashSquareSpec extends SquareSpec 
{
  public HashSquareSpec(int sx, int sy) 
  {
    super(sx,sy);
  }

  public HashSquareSpec(String codeString) 
  {
    super(codeString);
  }

  @Override  
  public int hashCode() 
  {  
    return this.toString().hashCode();  
  }  

  public boolean equals(HashSquareSpec other) 
  {
    if(this.toString().equals(other.toString()))
      return true;
    else
      return false;
  }
}

和 HashSquareSpec 的超类

public class SquareSpec {
  public int x;
  public int y;

  public SquareSpec(int sx, int sy) {
      this.x = sx; 
      this.y = sy;
  }

  public SquareSpec(String codeString) {
      this.x = Integer.parseInt(codeString.substring(1,2));
      this.y = Integer.parseInt(codeString.substring(3,4));
  }

  public String toString() {
      return("(" + x + "," + y + ")");
  }

  public boolean equals(SquareSpec other) {
      return (other.x == this.x  && 
              other.y == this.y );
    }
  }

尽管有许多不同的 hashCode 变体和 Eclipse equals 和 hashCode 生成,firedShots 数据结构仍然接受重复。我的代码有什么问题?

4

2 回答 2

3

您在正确的轨道上,覆盖hashcodeand equals,除非您错误地覆盖了in (and )中的equals方法。Object参数必须是. 因为它没有被覆盖,所以调用from ,它比较对象引用以查看它们是否是同一个对象。他们不是,所以“重复”是允许的。HashSquareSpecSquareSpecObjectequalsObject

尝试:

@Override
public boolean equals(Object other) 
{
  if(this.toString().equals(other.toString()))
    return true;
  else
    return false;
}

您还应该测试是否othernull,然后确保它other是相同的类型。

包括@Override注释,以便编译器在该方法实际上没有覆盖任何内容时会抱怨。

于 2014-03-27T23:56:16.603 回答
0

它仍然可以接受,因为您没有覆盖该equals方法。您需要覆盖boolean equals(Object). 问题是您正在定义一个新方法,例如boolean equals(SquareSpec).

这是LinkedHashSet#add(T)最终调用的方法:

HashMap#put(K, V)

@Override public V put(K key, V value) {
    if (key == null) {
        return putValueForNullKey(value);
    }

    int hash = secondaryHash(key.hashCode());
    HashMapEntry<K, V>[] tab = table;
    int index = hash & (tab.length - 1);
    for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
        if (e.hash == hash && key.equals(e.key)) {
            preModify(e);
            V oldValue = e.value;
            e.value = value;
            return oldValue;
        }
    }

如您所见,它使用hashCodeand进行比较equals(Object)

于 2014-03-27T23:56:15.600 回答