hashmap出现重复key的情况

来源:互联网 发布:skype6 下载 mac 编辑:程序博客网 时间:2024/06/05 03:03

刚刚写完hashmap的源码解读,然后在对hashhmap中使用put的时候数组的首节点覆盖,链节点不覆盖的,徘徊不解的情况下,在网上搜看到的一篇文章中的问题感到很好奇,下去特别实践实践。最后终于搞明白了。文章地址:http://blog.csdn.net/dandaoyi/article/details/40126429

其中代码例子:有model:Person类

package test3;

public class Person {
private String name;
private int age;

public Person(String name,int age) {
    // TODO Auto-generated constructor stub
    this.age=age;
    this.name=name;
}

public void setAge(int age) {
    this.age = age;
}
public void setName(String name) {
    this.name = name;
}
public int getAge() {
    return age;
}
public String getName() {
    return name;
}


@Override
    public int hashCode() {
        // TODO Auto-generated method stub
    final int prime=33;
    int result=1;
    result=prime*result+age;
    result=prime*result+((name==null)?0:name.hashCode());
    return result;
    }

@Override
    public boolean equals(Object object) {
        // TODO Auto-generated method stub
    
    if (this==object) {
        return true;
    }if(object==null) {
        return false;
    }if (getClass()!=object.getClass()) {
        return false;
    }
    Person other=(Person)object;
     if (age != other.age)  
         return false;  
     if (name == null) {  
         if (other.name != null)  
             return false;  
     } else if (!name.equals(other.name))  
     { return false;  
     }
     return true;
    }
@Override
    public String toString() {
        // TODO Auto-generated method stub
        return "Person [name=" + name + ", age=" + age + "]";
    }


}

有测试代码类:

package test3;

import java.util.HashMap;
import java.util.Map;

public class test2 {
    public static void method1(){
        
        Person p1 = new Person("xiaoer",1);  
        Person p2 = new Person("san",4);  
          
        Map<Person,String> maps = new HashMap<Person,String>();  
        maps.put(p1, "1111");  
        maps.put(p2, "2222");  
        System.out.println(maps);  
          
        maps.put(p2, "333");  
        System.out.println(maps);  
       System.out.println(p1.hashCode());   
        p1.setAge(5);  
        System.out.println(maps);  
          
     
       maps.put(p1, "1111");    

        System.out.println(p1.hashCode());
        
        
        System.out.println(p1.hashCode());
        System.out.println(maps);  
        System.out.println(maps.get(p1));    
}
    public static void main(String[] args) {
        method1();
    }
}

最后,打印的结果很有趣:

可以看出:在上图中竟然出现了相同的key,为什么?

首先在明白上面的问题的前提是你要知道一个知识点:在数组中存的是对象的引用,不是对象。

我对上面的程序debug了一遍,发现原来是因为在p1刚放进去的时候是由Person的name和age的hashcolde散列码共同构成的,但是,但是,但是,重要说3遍!由于放进去的只是对象的引用,所以当下面的p1.setAge(5);  时候所以数组中的值发生变化,也说明他本身的hashcode即hash发生变化,但是,但是,但是,重要说3遍!尽管现在他的散列码发生变化,然而他已经在hashmap数组中了,他位置没有发生变化,即意味着他现在变化后的hash的位置空着,所以对hashmap添加的时候就又添加进去,方在现在的位置上!!废话不多说,上图

第一张

第二张

第三张


第四张

好了上面的图按顺序,第一张是在setage之前的map图,第二张是setage之后的图,第三张,是put之后的图,发现在第一张和第二张中不能看hashcode,坑啦,最后只能打印出来,就有了第四张,由图可以看出来,还是符合结论的!

遗留的问题就是,上面get(p1)的到的是最后放入的结果!先放入的p1对应的结果无法获取。

好了,上面已经知道原因了,那上面问题会照成什么问题????对象存在旧的位置,而照成无法获取,不能得到,但是他有占据空间,如果有很多个这样的无用对象呢?这就是内存泄漏!!!!所以以后在涉到一系列的数组的操作的时候,都有注意对象的引用问题啦!!


好记性不如烂笔头,写给几年后的自己!!!

原创粉丝点击