为什么我不能用覆盖删除对象

时间:2016-07-17 00:55:13

标签: java

在集合测试中,我创建了一个名为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);
}

1 个答案:

答案 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来进行正确的本地化排序。