LinkedHashSet不删除重复项

时间:2014-03-27 23:53:53

标签: java coordinates hashcode no-duplicates linkedhashset

我正在尝试创建一个搜索算法,将坐标对存储在名为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等于和hashCode生成,但是 firedShots数据结构不断接受重复。我的代码出了什么问题?

2 个答案:

答案 0 :(得分:3)

您走在正确的轨道上,覆盖hashcodeequals,除非您错误地覆盖HashSquareSpec(和SquareSpec)中的equals method from Object。参数必须是Object。因为它未被覆盖,所以调用来自equals的{​​{1}},它会比较对象引用以查看它们是否是同一个对象。他们不是,所以&#34;重复&#34;是允许的。

尝试:

Object

您还应该测试@Override public boolean equals(Object other) { if(this.toString().equals(other.toString())) return true; else return false; } 是否为other,然后确保null的类型相同。

包含other注释,以便编译器在方法实际上不覆盖任何内容时会抱怨。

答案 1 :(得分: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;
        }
    }

如您所见,它使用hashCodeequals(Object)进行比较。