HashMap对于Java开发人员来说,应该是一种非常非常熟悉的数据结构了,应用场景相当广泛。
本文重点不在于介绍如何使用HashMap,而是关注在使用HashMap过程中,可能会导致内存泄露的情况,下面将以示例的形式展开具体介绍。
为了更快的看到java.lang.OutOfMemoryError,我们可以配置下IDEA的JVM参数,简单配置下初始堆和最大堆参数为5M,-Xms5m -Xmx5m,如下图
不重写hashcode、equals
public class Test1 {
public static void main(String[] args) {
Map<People, Integer> map = new HashMap<People, Integer>(1000);
int count = 0;
while (true){
People p = new People("zhangsan",10);
map.put(p,1);
count++;
if (count % 1000 == 0){
System.out.println("map size: " + map.size());
System.out.println("运行"+count+"次后,可用内存剩余"+Runtime.getRuntime().freeMemory()/(1024*1024)+"MB");
}
}
}
}
class People{
private String name;
private Integer age;
public People(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
结果分析:Object 的 hashcode 方法是本地方法,也就是用 c 或 c++ 实现的,该方法直接返回对象的内存地址,让后再转换整数,每次new的对象地址都不一样,就导致对象越来越多,最终触发OutOfMemoryError。
建议:当想要使用对象作为HashMap的key时,可以考虑使用不可变对象作为HashMap的key,比如常用的String类型,或者确保使用不可变的成员属性来生成hashcode;
- HashMap中数据在数组中的存放位置,是取决于Key对象的 hashCode() 方法的。
- 一个对象的hashCode() 方法的值,一般来说都是和对象的内容相关的。那么,如果Key对象的成员取值变化了,它的hashCode() 基本上也会变化。
- 在存放进去的时候,和取出数值的时候,都是依赖Key 对象的hashCode计算的。
为什么重写equals还要重写hashcode方法
可以参考这篇文章
https://donglin.blog.csdn.net/article/details/129018073