HashSet内存泄露

举个栗子

public class Person {
    String name;
    int age;

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.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;
        Person other = (Person) obj;
        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;
    }
}

很简单的Person类,为了使用HashSet,Person类最好复写hashcodeequals方法

测试

import java.util.HashSet;
import java.util.Set;

public class PersonTest {

    public static void main(String[] args) {
        Set<Person> ps = new HashSet<>();
        Person p = new Person("joshua", 25);

        ps.add(p);
        p.name = "aw";
        ps.remove(p);
        System.out.println(ps.size());
    }
}

程序输出结果为:1

分析

Person的hash值由name和age共同计算得出

  1. 当p插入ps中时,根据name与age计算hash值进行插入
  2. 插入后改变了对象p的name值
  3. remove(p)时根据新的name与age计算hash值进行查找(此hash值不同于原hash值)
  4. 由于hash值不同,在HashSet对应的位置无法查找到该对象,因此无法删除
  5. 由于该对象的引用还保存在ps中,所以无法回收(产生内存泄露)

结论

  1. 对象加入Hash表中之后不要更改用于计算Hash值的属性
  2. 会发生改变的属性不要用于计算Hash值

PS:若对HashSet的实现有疑问,可以提出来哦
HashSet的实现原理在这里

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容