现在的位置: 首页 > 综合 > 正文

HashMap存取过程中改变key值导致的内存泄露

2018年06月05日 ⁄ 综合 ⁄ 共 3421字 ⁄ 字号 评论关闭

HashMap是通过键值对的形式来存储数据的,把某个对象存入Map后,我们在外部把key的值修改,然后再通过这个新的key值从HashMap集合中获取元素,这时候可以取出原来的值吗?

我们通过一个测试示例来说明:

class User{
	private Integer uid;
	private String uname;
	
	public User(Integer uid, String uname) {
		this.uid = uid;
		this.uname = uname;
	}

	public Integer getUid() {
		return uid;
	}

	public void setUid(Integer uid) {
		this.uid = uid;
	}

	public String getUname() {
		return uname;
	}

	public void setUname(String uname) {
		this.uname = uname;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((uid == null) ? 0 : uid.hashCode());
		result = prime * result + ((uname == null) ? 0 : uname.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (uid == null) {
			if (other.uid != null)
				return false;
		} else if (!uid.equals(other.uid))
			return false;
		if (uname == null) {
			if (other.uname != null)
				return false;
		} else if (!uname.equals(other.uname))
			return false;
		return true;
	}
	
	
}
public class MapTest {

	public static void main(String[] args) {

		/*创建一个User对象*/
		User user = new User(1, "习近平");
		
		/*创建一个Map集合*/
		Map<User, String> maps = new HashMap<User, String>();
		
		/*往集合中添加数据【key为User对象,value为一个字符串】*/
		maps.put(user, "中国梦");
		
		/*打印user的hashCode()值*/
		System.out.println("user的hashCode值:" + user.hashCode());
		
		/*遍历获取key值,然后把key值改掉*/
		for (Entry<User, String> entry : maps.entrySet()){
			
			if (entry.getKey().getUname().equals("习近平")){
				
				entry.getKey().setUname("胡锦涛");
			}
		}
		
		/*再次打印user的hashCode值*/
		System.out.println("key值改变后,user的hashCode值:" + user.hashCode());
		
		/*通过迭代器获取key,然后通过key获取value值*/
		Iterator<User> it = maps.keySet().iterator();
		
		/*遍历获取value值*/
		while(it.hasNext()){
			
			User u = (User) it.next();
			
			System.out.println("user:" + maps.get(u));
		}
	}

}

程序最终的输出结果为null !!!!

HashMap在存储元素时如果key值发生变化,hashCode值也会变化!

也就是说我们在使用HashMap存取的过程中,不要轻易改变key的值,如果改变了,就会导致取不出最初的value值,也就是说当初的那个value值留在了内存中,成为了垃圾,如果越积越多,最终就会导致内存泄露咯!!!!!

所以,当key值改变以后,user对象的hashCode值也发生了变化,从而导致取不出当初对应的那个value值了,其实这是可以改变的,我们可以重写hashCode()方法使得hashCode值不依赖于我们修改的属性!

如下修改【修改hashCode()方法使要更新的uname属性不参加hashCode的算法】:

class User{
	private Integer uid;
	private String uname;
	
	public User(Integer uid, String uname) {
		this.uid = uid;
		this.uname = uname;
	}

	public Integer getUid() {
		return uid;
	}

	public void setUid(Integer uid) {
		this.uid = uid;
	}

	public String getUname() {
		return uname;
	}

	public void setUname(String uname) {
		this.uname = uname;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((uid == null) ? 0 : uid.hashCode());
		//result = prime * result + ((uname == null) ? 0 : uname.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (uid == null) {
			if (other.uid != null)
				return false;
		} else if (!uid.equals(other.uid))
			return false;
		if (uname == null) {
			if (other.uname != null)
				return false;
		} else if (!uname.equals(other.uname))
			return false;
		return true;
	}
	
	
}
public class MapTest {

	public static void main(String[] args) {

		/*创建一个User对象*/
		User user = new User(1, "习近平");
		
		/*创建一个Map集合*/
		Map<User, String> maps = new HashMap<User, String>();
		
		/*往集合中添加数据【key为User对象,value为一个字符串】*/
		maps.put(user, "中国梦");
		
		/*打印user的hashCode()值*/
		System.out.println("user的hashCode值:" + user.hashCode());
		
		/*遍历获取key值,然后把key值改掉*/
		for (Entry<User, String> entry : maps.entrySet()){
			
			if (entry.getKey().getUname().equals("习近平")){
				
				entry.getKey().setUname("胡锦涛");
			}
		}
		
		/*再次打印user的hashCode值*/
		System.out.println("key值改变后,user的hashCode值:" + user.hashCode());
		
		/*通过迭代器获取key,然后通过key获取value值*/
		Iterator<User> it = maps.keySet().iterator();
		
		/*遍历获取value值*/
		while(it.hasNext()){
			
			User u = (User) it.next();
			
			System.out.println("user:" + maps.get(u));
		}
	}

}

此时就可以取出user对象咯!!!!!

抱歉!评论已关闭.