在每个覆盖了equals方法的类中,都必须覆盖hashCode方法。如果不这样做的话,就会违反hashCode的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这类集合包括HashMap和HashSet。
Object规范预定:
如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中的hashCode方法都必须产生同样的整数结果。
因没有覆盖 hashcode而违反的该关键约定:相等的对象必须具有相等的散列码( hash code)。根据类的equals方法,两个截然不同的实例在逻辑上有可能是相等的,但是根据 Object类的 hashcode方法,它们仅仅是两个没有任何共同之处的对象。因此,对象的 hashcode方法返回两个看起来是随机的整数,而不是根据第二个约定所要求的那样,返回两个相等的整数。
假设在 HashMap中用Phonenumber类的实例作为键:
Map<PhoneNumber, String> m = new HashMap<>();
m.put(new PhoneNumber(707, 867, 5309), "herohua");
此时,你可能期望m.get( new PhoneNumber(707,867,5309))
会返回"herohua"
,但它实际上返回的是null
。注意,这里涉及两个 Phonenumber实例:第一个被插入 HashMap中,第二个实例与第一个相等,用于从Map中根据 Phonenumber去获取用户名字。由于Phonenumber类没有覆盖 hashcode方法,从而导致两个相等的实例具有不相等的散列码,违反了 hashcode的约定。因此,put方法把电话号码对象存放在一个散列桶(hash bucket)中,get方法却在另一个散列桶中查找这个电话号码。即使这两个实例正好被放到同一个散列桶中,get方法也必定会返回null,因为 HashMap有一项优化,可以将与每个项相关联的散列码缓存起来,如果散列码不匹配,也就不再去检验对象的等同性。
网友评论