Set集合
1 概念与结构
Set集合结构图
Set集合概念:
-
Set是不包含重复元素 的集合。Set集合也是继承了Collection,所以Collection中的操作广场对Set集合同样适用。
-
HashSet和TreeSet是Set的实现
-
HashSet是基于Hash算法实现的,其性能通常优于TreeSet,我们通常都应使用HashSet,在我们需要排序的功能时,我们才使用TreeSet
2 HashSet
- 此类实现 Set 接口,底层由哈希表(实际为 HashMap 实例)实现。 对集合的迭代次序不作任何保证;
- 特别是,它不能保证迭代在一段时间内保持不变。
- 这个类允许 null 元素。
查看HashSet的本质
- 可以看到,内部由HashMap实现,key可以传入,value为final定义的常量作为占位符。
- HashSet的数据实际上就是HashMap的key的集合
// 使用HashMap存储数据,HashSet的数据实际为HashMap的key
private transient HashMap<E,Object> map;
// HashMap value占位符
private static final Object PRESENT = new Object();
构造函数
可以看到,创建HashSet的本质就是初始化HashMap。
// 空参构造函数,内部初始化map属性
public HashSet() {
map = new HashMap<>();
}
// 传入集合对象
public HashSet(Collection<? extends E> c) {
// 初始化map,计算map的容量
// 计算公式为 c.size/0.75f + 1,如果值小于16,则取值16。
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
// 将集合中的所有元素添加进去
addAll(c);
}
// 手动指定容量和加载因子
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
// 手动指定容量
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
常用api
add(E e)
add(E e) 添加指定元素:
public boolean add(E e) {
// 往map里添加元素,如果key已经存在则返回false,否则返回true
return map.put(e, PRESENT)==null;
}
contains(Object o)
contains(Object o) 判断是否包含指定元素:
public boolean contains(Object o) {
// 本质就是判断map中是否包含该key
return map.containsKey(o);
}
size()
size() 获取元素个数:
public int size() {
// 本质就是获取map的元素个数
return map.size();
}
isEmpty()
isEmpty() 判断集合是否为空:
public boolean isEmpty() {
// 本质就是判断map是否为空
return map.isEmpty();
}
remove(Object o)
remove(Object o) 删除指定元素:
public boolean remove(Object o) {
// 本质就是通过key删除map中的元素,如果该key存在,则返回true,否则返回false
return map.remove(o)==PRESENT;
}
clear()
clear() 清空集合:
public void clear() {
// 本质就是清空map
map.clear();
}
iterator()
iterator() 获取迭代器:
public Iterator<E> iterator() {
// 本质就是获取map key的迭代器
return map.keySet().iterator();
}
3 TreeSet
基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。