一、Set概述
1、Set继承了Collection的接口,集合中不包含重复的元素,并且最多存在一个空的元素;
2、HashSet和TreeSet是Set的两个实现类。HashSet依赖于HashMap,他的元素是无序的,TreeSet依赖于TreeMap,元素是有序的;
二、HashSet解析
1、HashSet简介
(1)HashSet底层是用HashMap来存储的,能够存储一个null值,元素时无序的。
(2)HashSet是非线程安全的,在多线程环境下使用add、delete等操作,会发生快速失败,所以可以在使用的时候加上同步锁。
2、HashSet的底层存储
由这两句可以看出HashSet的存储使用的是HashMap,他的value值使用的是一个虚拟的默认值
//底层是用HashMap来存储元素
private transient HashMap<E,Object> map;
//定义一个虚拟的Object作为HashMap的value
private static final Object PRESENT = new Object();
3、HashSet初始化方法
初始化HashSet有下面四种方法,但是从方法的实现中都可以看到实际上是初始化对应的HashMap
//初始化一个HashSet:是用的是初始化HashMap的方法,默认的容量为17,负载因子0.75
public HashSet() {
map = new HashMap<>();
}
//初始化包含固定集合的HashSet:先初始化一个HashMap,然后经集合中的元素添加到map中
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
//初始化指定容量和负载因子的HashSet:实际上也是指定HashMap的容量和负载因子
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
//初始化指定容量的HashSet:默认负载因子
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
4、HashSet对应的方法
下面是HashSet中对应的方法,如果已经了解到HashMap对应的方法的实现过程,那么理解这几个方法就很简单,他们的实现都是基于HashMap来进行的,从这几个方法中也可以看出,HashSet中的值实际上是对应了HashMap中的key值,而HashMap中的value就是前面说到的默认的对象,而在HashMap中key值是不能重复的,这也限制了HashSet中的元素不能重复。
//返回HashSet中元素的个数
public int size() {
return map.size();
}
//判断HashSet是否为空
public boolean isEmpty() {
return map.isEmpty();
}
//判断HashSet中是否包含某元素:也就是判断HashMap中是否已经包含对应的key值
public boolean contains(Object o) {
return map.containsKey(o);
}
/**
* 向HashSet中插入一个元素:将该元素做为key值,value为默认的object插入到HashMap中,
* 如果set中不包含该元素返回true值,已包含返回false值
* @param e
* @return
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
/**
* 删除Set中的一个元素,实际上是删除的是Map中对用的key值
* 如果HashMap中对应的key值的value值为默认的Object,返回true,否则返回false
* @param o
* @return
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
//清空HashSet
public void clear() {
map.clear();
}
5、HashSet的遍历方式
HashSet有两种遍历方式:一种是使用迭代器的形式,一种是使用增强型for循环的方式
Iterator<Object> it = set.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
for(Object o: set) {
System.out.println(o);
}
6、HashSet总结
相比较而言,HashSet的源码的实现比较简单,如果对HashMap已经熟悉,那么很容易理解HashSet:
(1)HashSet中的元素是无序的,基于HashMap实现,HashMap中的元素也是无序的;
(2)HashSet中的元素时不能重复的,HashSet中的值对应的是HashMap中的key值,而key值不能重复;
(3)HashSet是非线程安全的。
三、TreeSet解析
1、TreeSet简介
(1)TreeSet是通过TreeMap实现的,也是基于红黑树的存储结构;
(2)TreeSet中不允许存在null对象;
(3)TreeSet中的元素时有序的;
2、TreeSet的构造方法
TreeSet有四种构造方法,分别对应的是TreeMap的构造方法,在这里也可以看出TreeSet都是通过闯进一个TreeMap来存储元素,
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
//初始化一个TreeSet:使用自认顺序排序,调用的是TreeMap的初始化方法
public TreeSet() {
this(new TreeMap<E,Object>());
}
//初始化一个指定排序方式的TreeSet:调用对应的TreeMap初始化方法
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
//初始化一个包含指定集合元素的TreeSet:先初始化一个TreeMap,使用自然排序,然后将集合中的元素添加到map中
public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
}
//创建一个包含指定Set的TreeSet:先创建一个指定的排序的TreeMap,然后将元素加入到map中
public TreeSet(SortedSet<E> s) {
this(s.comparator());
addAll(s);
}
3、TreeSet中对应的方法
下面是TreeSet中最常用的几个方法,他的实现都是基于TreeMap对应的方法实现的,与HashSet一样,TreeSet中的值对应的是TreeMap中的key值,所以不允许存在重复的元素和值。
//TreeSet中的元素个数,使用的是TreeMap的size方法
public int size() {
return m.size();
}
//判断TreeSet是否为空,使用的是TreeMap的isEmpty方法
public boolean isEmpty() {
return m.isEmpty();
}
//判断TreeSet中是否包含某值,实际上是判断TreeMap中是否包含对应的key值
public boolean contains(Object o) {
return m.containsKey(o);
}
/**
* 向TreeSet中添加一个元素:实际上是向TreeMap中添加一个key对对应元素,value为默认值的过程,
* 如果TreeMap中返回的结果为空,表示该元素之前在TreeMap中不存在,不为空表示已存在
* @param e
* @return
*/
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
/**
* 删除TreeSet中的元素,实际上是删除TreeMap中key为o的元素
* 如果TreeMap中返回的结果是默认的PRESENT,表示该元素在Set中存在,那么结果为true,反之为false
* @param o
* @return
*/
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
}
//清空TreeSet中的元素,实际上是清空TreeMap中的元素
public void clear() {
m.clear();
}
4、TreeSet的遍历方式
TreeSet的可以使用迭代器进行遍历,也可以使用for循环进行遍历
Iterator it = set.iterator();
while(it.hasNext()) {
System.out.println(it1.next());
}
for(Object o: set) {
System.out.println(o);
}
5、TreeSet总结
(1)TreeSet的底层实现是基于TreeMap实现的,为了更好的理解TreeSet,建议先理解TreeMap的结构;
(2)TreeSet中的元素时有序的,不存在重复的元素和null值;
四、Set总结
1、set中不允许存在重复的元素;
2、HashSet是基于HashMap实现的,有HashMap有相同的特性;
3、TreeSet是基于TreeMap实现的,他包含的方法都是根据TreeMap中对应的方法实现;
4、理解set的时候建议首先了解map的实现过程。