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对象咯!!!!!