本帖最后由 李易烜 于 2013-4-13 17:16 编辑
当我们重写了对象的equals方法,一般情况下(这里我指这些对象不需要放到Set或Map中仅仅是比较需要,或者虽然放到Set或Map中,但是get和set时用的是同一对象)是没有问题的,但是,有些情况下就不同了;举个例子- public class Person(){
- private int id;
- private String name;
- //define getter and setter here, omited
- public void equals(Object obj){
- if (!(obj instanceof Person))
- return false;
- return super.equals(obj) && ((Member) obj).getId() == this.getId();
- }
- }
复制代码 上述class中没有覆盖hashCode方法,因此这个时候用的是Object.hashCode()的返回值;我们来测试一下- public class TestHashCode extends TestCase {
- public void testMap() {
- Person p1 = new Person(1,"aaa"),p2 = new Person(1,"bbb");
- Map map = new HashMap();
- map.put(p1,p1);
- Member value = (Person)map.get(p2);
- System.out.println(value.getName());
- }
- }
复制代码 请注意,这两个对象是相等的,可以从equals()的定义看出来;运行TestHashCode ,结果是NullPointerException;
现在添加hashCode()到Person中- public int hashCode() {
-
- return this.getId() * 37 ;
- }
复制代码 重运行TestHashCode ;huh,我们想要的结果出现了,“aaa”
为什么添加person.hashCode()前,得不到person对象;因为java中默认的hashCode是根据对象的地址计算得到的,虽然p1.equals(p2)=true,但是p1,p1有不同的内存地址,所以有不同的hashCode;所以通过p2是不能得到value的,这个时候value==null;添加hashCode()后,两个对象有相同hashCode,所以能得到
java中Set是通过Map实现的,所以Map和Set的所有实现类都要注意这一点
HashMap是通过链地址法解决hash collision的,并且新对象都是添加到表头的(这个看了好久才明白,数据结构都还老师了) |