在集合测试中,我创建了一个名为Name的类,并覆盖了equals方法,如下所示,
class Name implements Comparable<Name>{
private String firstName, lastName;
Name(String firstName, String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
public String toString(){
return firstName + " "+lastName;
}
public boolean equals(Name name){
return firstName.equals(name.firstName) && lastName.equals(name.lastName);
}
public int hashCode(){
return firstName.hashCode();
}
但是当我在集合中测试remove()函数时,它是假的,并且名称(&#34; Andy&#34;,&#34; Light&#34;)仍然在集合中。我的代码出了什么问题?
public static void main(String[] args){
Collection c = new HashSet();
c.add("hello");
c.add(new Name("Andy","Light"));
c.add(new Integer(100));
c.remove("hello");
c.remove(new Integer(100));
System.out.println(c.remove(new Name("Andy","Light")));
System.out.println(c);
}
答案 0 :(得分:3)
有评论和答案说明您的hashCode()
方法与equals()
不一致,因为您在哈希码计算中未包含lastName
。他们都错了。
允许hashCode()
实现使用equals()
使用的值的子集。它会以这种方式导致更多的哈希码冲突,抵消了hashCode()
的速度提升与哈希桶性能降低的影响。子集哈希码可能没问题,这取决于具有相同Name
的{{1}}个对象的可能性。
您的问题是firstName
的签名错误。 为equals()
。
boolean equals(Object)
不覆盖boolean equals(Name)
,因此您实际上并未覆盖/实施boolean equals(Object)
方法,因此最终equals()
与hashCode()
的不一致(但不是其他人说的原因)。
如果添加equals()
注释,编译器就会遇到此问题。始终使用注释。
更改为:
@Override
这当然假设两者都不能为空。
正如@MickMnemonic在评论中所说:
忽略
中包含的字段,这被认为是不好的做法@Override public boolean equals(Object obj) { if (! (obj instanceOf Name)) return false; Name that = (Name)obj; return this.firstName.equals(that.firstName) && this.lastName.equals(that.lastName); } @Override public int hashCode() { return this.firstName.hashCode(); }
要在计算中加入equals()
,请使用Objects.hash()
:
lastName
另外,作为@StephenB said in a comment:
您还需要添加
@Override public int hashCode() { return Objects.hash(this.firstName, this.lastName); }
方法,因为您正在实施compareTo
。
这里使用Comparable<Name>
作为参数,而不是Name
,因为Object
的泛型类型参数。
示例(如果按姓氏前面的名字排序):
Comparable
实现firstName / lastName lexicographical ordering。您可能希望使用compareToIgnoreCase()
或Collator
来进行正确的本地化排序。