一,前言
类实现Set接口,由哈希表支持(实际上是一个 HashMap集合)。HashSet集合不能保证的迭代顺序与元素存储顺序相同。HashSet集合,采用哈希表结构存储数据,保证元素唯一性的方式依赖于:hashCode()与equals()方法。
二,HashSet结构
2.1 什么是哈希表
哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放时,那么会根据这些对象的特有数据结合相应的算法,计算出这个对象在数组中的位置,然后把这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表。
当向哈希表中存放元素时,需要根据元素的特有数据结合相应的算法,这个算法其实就是Object类中的hashCode方法。由于任何对象都是Object类的子类,所以任何对象有拥有这个方法。即就是在给哈希表中存放对象时,会调用对象的hashCode方法,算出对象在表中的存放位置,这里需要注意,如果两个对象hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回的是true,那么就不会把第二个对象存放在哈希表中,如果返回的是false,就会把这个值存放在哈希表中。
2.2 哈希表存储结构
三,HashSet源码阅读
3.1 HashSet的继承关系
3.2 HashSet的构造方法
public HashSet() {} // 一个空的构造函数,new一个hashMap对象实例出来。默认初始容量是16 加载因子是0.75, public HashSet(Collection<? extends E> c) {} // 将一个新的collection转换为一个HashSet集合 public HashSet(int initialCapacity, float loadFactor) {} // 自己初始化容量和加载因子的大小 public HashSet(int initialCapacity) {} // 初始化容量大小,加载因子用默认的
3.3 HashSet的常用方法
public Iterator<E> iterator() {} // 转化成迭代器 public int size() {} // 基础集合长度 public boolean isEmpty() {} // 判断是否为空 public boolean contains(Object o) {} // 判断对象是否存在 public boolean add(E e) {} // 添加 public boolean remove(Object o) {} // 删除 public void clear() {} // 清空 @SuppressWarnings("unchecked") public Object clone() {} // 克隆 /** * @since 1.8 */ public Spliterator<E> spliterator() {} // 1.8
四,总结
保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。它是一个无序的集合(元素存与取的顺序可能不同),它不能存储重复的元素