其实学完了HashMap以后,对HashSet的学习真的非常简单。。实际上,HashSet的底层结构就是HashMap。
我们先来看HashSet的定义
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
HashSet的属性
// 版本序列号
static final long serialVersionUID = -5024744406713321676L;
// 键值Map
private transient HashMap<E,Object> map;
// 用作所有键对应的值,键所对应的值都相等
private static final Object PRESENT = new Object();
我们都知道HashSet中由于只包含键,不包含值,但底层实现又用到了键值对存储的HashMap,为适应HashMap存储,HashSet增加了一个PRESENT类域,所有的键都有同一个值(PRESENT)。
注意点
要确保重写hashCode()方法和equals()方法,这样才能比较对象的值是否相等,确保集合中没有储存相同的对象。如果不重写上述两个方法,将使用默认实现。
List接口,Set接口,Map接口之间的区别
至今为止,我们已经学过了List接口,Set接口,Map接口,下面我们来谈谈他们之间的区别
- List和Set是存储单列数据的集合,Map是存储键值对这样的双列数据的集合
- List存储的数据有序,允许有重复值,Map存储的数据无序,键不允许重复,但值允许重复,Set存储的数据无序,而且不允许重复。
List接口,Set接口,Map接口的实现类
List接口的实现类
- LinkedList:实现原理为链表,非线程安全
- ArrayList:实现原理为数组,非线程安全,效率高
- Vector:实现原理为数组,线程安全,效率低
Map接口的实现类
- HashMap:实现原理为哈希表,非线程安全,高效,支持 null 值和 null 键
- HashTable:线程安全,低效,不支持 null 值和 null 键
- LinkedHashMap:是 HashMap 的一个子类,保存了记录的插入顺序
- TreeMap:能够把它保存的记录根据键排序,默认是键值的升序排序
Set接口的实现类
HashSet:底层实现为HashMap,不允许集合中有重复的值
LinkedHashSet:继承于 HashSet,同时又基于 LinkedHashMap 来进行实现,底层使用的是 LinkedHashMap
HashMap与HashTable的区别
- HashMap 是线程不安全的,将键映射到值,不允许键重复,允许空键和空值,HashTable 是线程安全的,不允许 null 值作为一个
key 值或者 Value 值 - 由于非线程安全, HashMap的效率要较 HashTable 的效率高一些
- HashTable 是同步的,多个线程访问时不需要自己为它的方法实现同步,而 HashMap
在被多个线程访问的时候需要自己为它的方法实现同步
HashSet与HashMap的区别
- HashMap实现了Map接口,HashSet实现了Set接口
- HashMap用于存储键值对,HashSet仅仅用于存储对象
- HashMap使用put方法添加元素,HashSet使用add方法添加元素
- HashMap使用键(Key)计算Hashcode,HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false
- HashMap相对于HashSet较快