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 ответа

Решение

Вы на правильном пути, переопределяя hashcode а также equalsза исключением того, что вы неправильно переопределяете equals метод изObject в HashSquareSpec (а также SquareSpec). Параметр должен быть Object, Потому что это не переопределено, equals от Object называется, который сравнивает ссылки на объекты, чтобы увидеть, являются ли они одним и тем же объектом. Их нет, поэтому "дубликат" разрешен.

Пытаться:

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

Вы также должны проверить, если other является null а затем убедитесь, что other это тот же тип.

Включить @Override аннотации, так что компилятор будет жаловаться, если метод на самом деле ничего не переопределяет.

Он все еще принимает, потому что вы не переопределяете 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;
        }
    }

Как вы можете видеть, он сравнивает использование hashCode а также equals(Object),

Другие вопросы по тегам