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

来源:互联网 发布:淘宝给差评被砍死 编辑:程序博客网 时间:2024/06/09 14:22

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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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对象咯!!!!!

0 0
原创粉丝点击