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)
,