Java LinkedHashSet未删除重复项
我试图创建一个搜索算法,将坐标对存储在名为HashSquareSpec的包装类中。为了避免重复,并保持插入顺序,我将每个HashSquareSpec插入LinkedHashSet。尽管我已经重写了equals()方法和hashCode()方法,LinkedHashSet仍然接受两个具有 相同的坐标对Java LinkedHashSet未删除重复项,java,coordinates,hashcode,no-duplicates,linkedhashset,Java,Coordinates,Hashcode,No Duplicates,Linkedhashset,我试图创建一个搜索算法,将坐标对存储在名为HashSquareSpec的包装类中。为了避免重复,并保持插入顺序,我将每个HashSquareSpec插入LinkedHashSet。尽管我已经重写了equals()方法和hashCode()方法,LinkedHashSet仍然接受两个具有 相同的坐标对 public static void main(String [] args) { LinkedHashSet<HashSquareSpec> firedShots = new
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
以及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变体和eclipseequals以及hashCode生成,但是
firedShots数据结构不断接受重复项。我的代码有什么问题?它仍然可以接受,因为您没有覆盖
equals
方法。您需要重写布尔等于(对象)
。问题是您正在定义一个新方法,如boolean equals(SquareSpec)
下面是LinkedHashSet#add(T)
最终调用的方法:
HashMap#put(K,V):
@覆盖公共V输入(K键,V值){
if(key==null){
返回putValueForNullKey(值);
}
int hash=secondaryHash(key.hashCode());
HashMapEntry[]选项卡=表格;
int index=hash&(tab.length-1);
for(HashMapEntry e=tab[index];e!=null;e=e.next){
如果(e.hash==hash&&key.equals(e.key)){
预修改(e);
V oldValue=e.value;
e、 价值=价值;
返回旧值;
}
}
如您所见,它使用
hashCode
和equals(Object)
进行比较。您在正确的轨道上,覆盖了hashCode
和equals
,除非您错误地覆盖了HashSquareSpec
(和SquareSpec
)。该参数必须是对象
。因为它没有被重写,所以调用对象
中的等于
,比较对象引用以确定它们是否是同一对象。它们不是,所以允许“重复”
尝试:
您还应该测试other
是否为null
,然后确保other
为同一类型
包括
@Override
注释,这样如果方法实际上没有重写任何内容,编译器就会抱怨。这也不是一个好的等于实现;您应该执行instanceof
检查。(例如,您的实现不是对称的,因为这将等于字符串)@LouisWasserman非常正确,这就是为什么包含一个关于空检查和检查其他是否属于同一类型的句子的原因。
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 );
}
}
@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;
}
}
@Override
public boolean equals(Object other)
{
if(this.toString().equals(other.toString()))
return true;
else
return false;
}