HashSet底层和内存泄漏

HashSet底层和内存泄漏,第1张

HashSet底层和内存泄漏 1.什么是HashSet:
  • 一个单列集合;
  • 不保证set的迭代顺序,特别他不保证该顺序恒久不变;
  • 前身是HashTable(哈希表:线程安全);
  • 允许使用null元素
  • 此时先是不同步的,所以线程不安全。
2.HashSet底层:
  • HashSet的底层其实是一个HashMap;
  • HashSet数据结构:一个对象数组,数组中存有链表;
  • HashSet初始容量为16,加载因子为0.75;
         问题1.为什么说HashSet的值是不可重复的呢?
  1. 我们都知道HashMap是一个双列集合,而HashSet是单列集合;
  2. 当HashSet创建一个HashMap的时候,把HashSet只在HashMap的key一列存值;
  3. 而HashMap的key值是不可重复的,也就是说HashSet的值是不重复的。
    问题2:为什么说HashSet不保证原始顺寻恒久不变呢?
  1. 由于HashSet的加载因子为0.75,也就是说当HashSet的内存使用率为75%是一个分割线;
  2. 当内存使用率达到75%,那HashSet集合中的对象数组将进行扩容;
  3. 这时候HashSet中的 所有元素的顺序将尽数被打乱重新存入到HashSet中。
    问题3: HashSet如何存值?
  1. 首先每一个对象都有自己的HashCode;
  2. HashSet将依照这个HashCode对自己的容量进行取余;
  3. 根据这个余数,HashSet将这个值存入到对应的对象数组“下标”的链表中。
  4. 而这里又会出现一个小问题4(当两个对象,HashCode不相同,但是内容却完全相同的情况下如何存入HashSet中?数据去重)。
        从问题三咱们能引申出两个问题:          代码如下:        
Person p1 = new Person("张三",18);
Person p2 = new Person("张三",18);

HashSet set = new HashSet();
set.add(p1);
set.add(p2);
    问题4: 如果存入两个内容完全相同的对象,而HashSet要求我们数值不可重复,那我们 如何去重
  1. 首先我们知道这两个对象虽然内容一样,但是也没有完全一样,因为他们引用的内存空间不是同一块内存空间;
  2. 所以两个不一样的对象,他们的HashCode也是不一样的(极大概率);
  3. 这也就意味着,在实体类中没有重写hashCode()和equals()方法的时候,他们都能存到HashSet中,而且不被覆盖;
  4. 所以我们在 创建实体类的时候要重写hashCode()和equals(),确保两个内容完全相同的对象只能插入一个到HashSet中。
    问题5:内存泄漏
  • 什么是内存泄漏?
        以实例为例:
  1. 在我们重写了hashCode()和equals()方法之后,对象会根据hashCode()方法,将对象的属性加入到一个算术中计算,得出hashCode;
  2. 当我们把这个对象存入HashSet后,我们突然要更改这个对象的属性,当然这个时候我们还能找到这个对象并更改其内容;
  3. 而在我们更改了这个对象的属性之后他的HashCode也会随之改变;
  4. 当我们再次访问HashSet来查找这个对象的时候,新生成的HashCode会让我们无法找到原来的对象,比如删除该对象就无法删除;
  5. 这,就是内存泄漏!
  • 那我们如何避免?
  1. 在重写HashCode()方法的时候,把可能之后会有变化的属性去掉,只留下不会进行更改的属性。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4674251.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-06
下一篇 2022-11-07

发表评论

登录后才能评论

评论列表(0条)

保存