说一下 HashSet 的实现原理?
HashSet 是基于 HashMap 实现的,HashSet的值存放于HashMap的key上,HashMap的value统一为
PRESENT,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层
HashMap 的相关方法来完成,HashSet 不允许重复的值。
HashSet如何检查重复?HashSet是如何保证数据不可重复的?
向HashSet 中add ()元素时,判断元素是否存在的依据,不仅要比较hash值,同时还要结合equles 方法比较。
HashSet 中的add ()方法会使用HashMap 的put()方法。
HashMap 的 key 是唯一的,由源码可以看出 HashSet 添加进去的值就是作为 HashMap 的key,并且
在HashMap中如果K/V相同时,会用新的V覆盖掉旧的V,然后返回旧的V。所以不会重复( HashMap
比较key是否相等是先比较 hashcode 再比较equals )。
以下是HashSet 部分源码:
1 private static final Object PRESENT = new Object(); 2 private transient HashMap<E,Object> map; 3 4 public HashSet() { 5 map = new HashMap (); 6 } 7 8 public boolean add(E e) { 9 // 调用HashMap的put方法,PRESENT是一个至始至终都相同的虚值 10 return map.put(e, PRESENT)==null; 11 }
hashCode()与equals()的相关规定:
- 如果两个对象相等,则hashcode一定也是相同的。
- 两个对象相等,对两个equals方法返回true。
- 两个对象有相同的hashcode值,它们也不一定是相等的。
- 综上,equals方法被覆盖过,则hashCode方法也必须被覆盖。
- hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。
==与equals的区别
- ==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同
- ==是指对内存地址进行比较 equals()是对字符串的内容进行比较
- == 指引用是否相同 equals()指的是值是否相同
HashSet与HashMap的区别
说一说HashSet的底层结构
HashSet是基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。它封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
说一说TreeSet和HashSet的区别
HashSet、TreeSet中的元素都是不能重复的,并且它们都是线程不安全的,二者的区别是:
- HashSet中的元素可以是null,但TreeSet中的元素不能是null;
- HashSet不能保证元素的排列顺序,而TreeSet支持自然排序、定制排序两种排序的方式;
- HashSet底层是采用哈希表实现的,而TreeSet底层是采用红黑树实现的。