解读:
类A覆写了hashCode方法,并采用A的属性value来生成A的hashCode。使用HashSet作为集合对象,把类A的一个对象a加入到HashSet中后,如果对象a的属性value发生了变化,则a的hashCode()方法返回的值也就发生变化,则无法将对象a从HashSet中删除。
案例:
问题代码:
//重新hashCode
public int hashCode()
{
int result;
result = name.hashCode() + address.toLowerCase().hashCode();
return result;
}
..................
HashSet<Email> set = new HashSet<Email>();
set.add(new Email("abc","xxx.com"));
for(Iterator<Email> i = set.Iterator();i.hashNext();)
{
Email mail = i.next();
mail.address = "kkk.com";
set.remove(mail);
}
System.out.println(set.size());
该程序片段最后的结果是1,修改了HashSet中对象的值后,将对象从HashSet中删除失败了。
正确代码:
预防措施如下:
1、如果覆写了equals方法,必须同时覆写hashCode方法。
2、equals方法和hashCode方法应避免使用易变的属性,避免该对象的hashCode频繁变化。
3、当对象被加入到HashSet(或作为Key加入到HashMap)后,应该避免该对象的hashCode发生变化。
//如果需要对Email的address属性进行修改,那么在重新hashCode方法时,避免使用易变的属性address
public int hashCode()
{
int result;
result = name.hashCode();
return result;
}