TreeSet作为Set接口实现类中的最后一个,它的原理其实也和HashSet、LinkedHashSet差不多,它主要是建立在TreeMap之上。
先继续熟悉它所处的结构体系:
从上图可以看出TreeSet和HashSet属于同一层级,唯一的区别是它可以对容器内的元素进行一定规则的排序。
继续看其继承体系:
TreeSet与HashSet继承自同一个抽象类,即Abstract类。
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
从上可以看出TreeSet并没有直接实现Set接口,而是和TreeMap类似,实现了NavigableSet接口,那么来看看该接口的主要提供方法:
public interface NavigableSet<E> extends SortedSet<E> {
E lower(E e);
//获得小于e的最大元素
E floor(E e);
//获得不大于e的最大元素
E ceiling(E e);
//获得不小于e的最小元素
E higher(E e);
//获得大于e的最小元素
E pollFirst();
//获得并删除第一个元素
E pollLast();
//获得并删除最后一个元素
Iterator<E> iterator();
//获得迭代器
NavigableSet<E> descendingSet();
//获得逆序的Set
Iterator<E> descendingIterator();
//获得逆序的Set迭代器
NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive);
//获得子Set
NavigableSet<E> headSet(E toElement, boolean inclusive);
//获得首部子Set
NavigableSet<E> tailSet(E fromElement, boolean inclusive);
//获得尾部子Set
SortedSet<E> subSet(E fromElement, E toElement);
//获得SortedSet类型的子Set
SortedSet<E> headSet(E toElement);
//获得SortedSet类型的首部子Set
SortedSet<E> tailSet(E fromElement);
//获得SortedSet类型的尾部子Set
}
public interface SortedSet<E> extends Set<E> {
Comparator<? super E> comparator();
//获得比较器
SortedSet<E> subSet(E fromElement, E toElement);
//获得子Set
SortedSet<E> headSet(E toElement);
//获得首部子Set
SortedSet<E> tailSet(E fromElement);
//获得尾部子Set
@Override
default Spliterator<E> spliterator() {
//获得分割器
return new Spliterators.IteratorSpliterator<E>(
this, Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED) {
@Override
public Comparator<? super E> getComparator() {
return SortedSet.this.comparator();
}
};
}
}
从上面代码中可以看出,NavigableSet和NavigableMap类似,都是对于边界值以及子Set进行处理的方法,而SortedSet和SortedMap类似,属于拥有比较其的Set。
接下来继续看其成员变量:
private transient NavigableMap<E,Object> m;
//私有成员变量,不可序列化,一个导航map,map中键值对分别为E和Object
private static final Object PRESENT = new Object();
//私有静态常量,当前对象,即用于填充键值对中的value值,不使用
也许看到这里有些疑惑,不是说TreeSet是建立在TreeMap上面么,为什么成员变量中没有TreeMap而只有一个NavigableMap。这里绕了一下,NavigableMap只是一个接口,因此此成员变量应该是接口的实例变量,而NavigableMap接口的实现类就是TreeMap。剩下的PRESENT就不用再多说了。
接下来看一看构造器:
TreeSet(NavigableMap<E,Object> m){
//构造器1,传入map类型的集合
this.m = m;
}
public TreeSet(){
//构造器2,空参构造器,调用第一个构造器,传入默认的map集合
this(new TreeMap<E,Object>());
}
public TreeSet(Comparator<? super E> comparator){
//构造器3,传入一个比较器,此时先创建一个使用传入该比较器的
//TreeMap集合,再将该集合作为参数传入第一个构造器中完成构造
this(new TreeMap<>(comparator));
}
public TreeSet(Collection<? extends E> c){
//构造器4,传入一个集合c,先调用第一个构造器,在将集合中
//的元素复制到TreeSet中
this();
addAll(c);
}
public TreeSet(SortedSet<E> s){
//构造器5,传入一个排好序的Set集合,先获得s的比较器,再通过比较器
//创建TreeSet,再将s中的内容复制到TreeSet中
this.(s.comparator);
addAll(s);
}
TreeSet有五个构造器,当传入的是同一种的NavigableMap<e,Object>的接口实现类时,则直接将其引用赋给m就完成了;当传入的是比较器,则创建一个该比较器的TreeMap,再调用本类构造器将TreeMap传入,将其引用赋给m;当传入空参时,则创建一个无比较器的TreeMap,再调用本类构造器将TreeMap传入并将其引用赋给m;当传入的是一个普通的集合c,则先调用本类构造器创建一个无比较器的TreeMap,再将c中的元素依次复制到TreeMap中;当传入的是一个SortedSet集合s时,先用s的比较器创建一个相同比较器的TreeMap,再将s中的元素依次复制到TreeMap中。
下面再来看看常用方法:
1.add
public boolean add(E e){
//向TreeSet中增加一个元素,调用m中的增加方法,由于map
//中是不允许key值重复的,所以TreeSet也不允许元素重复
return m.put(e,PRESENT) == null;
}
同样,调用TreeMap中的put方法将元素e加入到键值对中的key中,但是和HashMap不同的时,如果传入的为null会抛出空指针异常。
2.remove
public boolean remove(Object o){
//删除TreeSet中的某一个元素,调用m中的删除方法
return m.remove(o) == PRESENT;
}
同理,删除方法
3.contains
public boolean contains(Object o){
//判断TreeSet中是否含有某一个元素
return m.containsKey(o);
}
判断TreeSet中是否含有某一个元素
4.size
public int size(){
//获得TreeSet的元素数量,即m中的结点数量
return m.size();
}
获取TreeSet中的元素个数。
5.isEmpty
public boolean isEmpty(){
//判断TreeSet是否为空,即判断m是否为空
return m.isEmpty();
}
判断TreeSet中是否为空
6.clear
public void clear(){
//清空TreeSet
m.clear();
}
清空TreeSet
7.获取某一个元素
public E first(){
//获得第一个元素
return m.firstKey();
}
public E last(){
//获得最后一个元素
return m.lastKey();
}
public E pollFirst(){
//获得第一个元素
Map.Entry<E,?> e = m.pollFirstEntry();
return (e == null) ? null : e.getKey();
}
public E pollLast(){
//获得最后一个元素
Map.Enrty<E,?> e = m.pollLastEntry();
return (e == null) ? null : e.getKey();
}
8.获取集合
public Iterator<E> iterator(){
//获得迭代器
return m.navigableKeySet().iterator();
}
public Iterator<E> descendingIterator(){
//获得逆序迭代器
return m.descendingKeySet().iterator();
}
public NavigableSet<E> descendingSet(){
//获得逆序的Set集合
return new TreeSet<>(m.descendingMap());
}
总结:
异同 | HashSet | TreeSet |
底层实现 | 建立在HashMap上,散列表+链表+红黑树 | 建立在TreeMap上,红黑树 |
是否有序 | 无序 | 有序,可以自定义顺序或者采用元素本身的顺序 |
线程安全 | 不安全 | 不安全 |
元素可为null | 元素可以是null | 元素不可为null,否则会抛出空指针异常 |
效率 | 效率较低 | 效率较高 |
总源码
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{ //此TreeSet集合主要是建立在TreeMap集合的基础上的,使用其中键值对中的
//key值用与存储元素,将value值都默认为Object类PRESENT,不予使用
private transient NavigableMap<E,Object> m;
//私有成员变量,不可序列化,一个导航map,map中键值对分别为E和Object
private static final Object PRESENT = new Object();
//私有静态常量,当前对象,即用于填充键值对中的value值,不使用
TreeSet(NavigableMap<E,Object> m){
//构造器1,传入map类型的集合
this.m = m;
}
public TreeSet(){
//构造器2,空参构造器,调用第一个构造器,传入默认的map集合
this(new TreeMap<E,Object>());
}
public TreeSet(Comparator<? super E> comparator){
//构造器3,传入一个比较器,此时先创建一个使用传入该比较器的
//TreeMap集合,再将该集合作为参数传入第一个构造器中完成构造
this(new TreeMap<>(comparator));
}
public TreeSet(Collection<? extends E> c){
//构造器4,传入一个集合c,先调用第一个构造器,在将集合中
//的元素复制到TreeSet中
this();
addAll(c);
}
public TreeSet(SortedSet<E> s){
//构造器5,传入一个排好序的Set集合,先获得s的比较器,再通过比较器
//创建TreeSet,再将s中的内容复制到TreeSet中
this.(s.comparator);
addAll(s);
}
public Iterator<E> iterator(){
//获得迭代器
return m.navigableKeySet().iterator();
}
public Iterator<E> descendingIterator(){
//获得逆序迭代器
return m.descendingKeySet().iterator();
}
public NavigableSet<E> descendingSet(){
//获得逆序的Set集合
return new TreeSet<>(m.descendingMap());
}
public int size(){
//获得TreeSet的元素数量,即m中的结点数量
return m.size();
}
public boolean isEmpty(){
//判断TreeSet是否为空,即判断m是否为空
return m.isEmpty();
}
public boolean contains(Object o){
//判断TreeSet中是否含有某一个元素
return m.containsKey(o);
}
public boolean add(E e){
//向TreeSet中增加一个元素,调用m中的增加方法,由于map
//中是不允许key值重复的,所以TreeSet也不允许元素重复
return m.put(e,PRESENT) == null;
}
public boolean remove(Object o){
//删除TreeSet中的某一个元素,调用m中的删除方法
return m.remove(o) == PRESENT;
}
public void clear(){
//清空TreeSet
m.clear();
}
public boolean addAll(Collection<? extends E> c){
if(m.size() == 0 && c.size() > 0 && c instanceof SortedSet && m instanceof TreeMap){
//首先判断m中是否是空的,c中是否有元素,c是否属于SortedSet体系中,m是否属于TreeMap体系中
SortedSet<? extends E> set = (SortedSet<? extends E>) c;
//先将c强制类型转换为SotredSet类型的Set集合set
TreeMap<E,Object> map = (TreeMap<E,Object>) m;
//再将m强制类型转换为TreeMap类型的map集合map
Comparator<?> cc = set.comparator();
//再获得set的比较器cc
Comparator<? super E> mc = map.comparator();
//获得map的比较器Mc
if(cc == mc || (cc != null && cc.equals(mc))){
//如果两个比较器相同,则调用Map中的建树方法将
//set中的元素-默认value值全都建成一颗红黑树
map.addAllForTreeSet(set,PRESENT);
return true;
//如果成功,则返回true
}
}
return super.addAll(c);
//否则调用父类方法进行增加
}
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive){
//获得子Set,返回调用m的subMap方法
return new TreeSet<>(m.subMap(fromElement,fromInclusive,toElement,toInclusive));
}
public NavigableSet<E> headSet(E toElement, boolean inclusive){
//获得首部子Set
return new TreeSet<>(m.headSet(toElement,inclusive));
}
public NavigableSet<E> tailSet(E fromElement, boolean inclusive){
//获得尾部子Set
return new TreeSet<>(m.tailMap(fromElement,inclusive));
}
public SortedSet<E> subSet(E fromElement, E toElement){
//获得子Set,默认包含开始元素,不包括结束元素
return subSet(fromElement,true,toElement,false);
}
public SortedSet<E> headSet(E toElement){
//获得首部子Set,默认不包括结束元素
return headSet(toElement,false);
}
public SortedSet<E> tailSet(E fromElement){
//获得尾部子Set,默认包括开始元素
return tailSet(fromElement,true);
}
public Comparator<? super E> comparator(){
//获得TreeSet中的比较器
return m.comparator();
}
public E first(){
//获得第一个元素
return m.firstKey();
}
public E last(){
//获得最后一个元素
return m.lastKey();
}
public E lower(E e){
//获得小于传入元素e的最大元素、
return m.lowerKey(e);
}
public E floor(E e){
//获得不大于e的最大元素
return m.floorKey(e);
}
public E ceiling(E e){
//获得不小于e的最小元素
return m.ceilingKey(e);
}
public E higher(E e){
//获得大于e的最小元素
return m.higherKey(e);
}
public E pollFirst(){
//获得第一个元素
Map.Entry<E,?> e = m.pollFirstEntry();
return (e == null) ? null : e.getKey();
}
public E pollLast(){
//获得最后一个元素
Map.Enrty<E,?> e = m.pollLastEntry();
return (e == null) ? null : e.getKey();
}
@SuppressWarnings("unchecked")
public Object clone(){
//克隆TreeSet
TreeSet<E> clone;
try{
clone = (TreeSet<E>)super.clone();
}catch(CloneNotSupportedException e){
throw new InternalError(e);
}
clone.m = new TreeMap<>(m);
return clone;
}
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
//写出操作
s.defaultWriteObject();
//写出其他隐藏的东西
s.writeObject(m.comparator);
//写出比较器
s.writeInt(m.size());
//写出TreeSet中的元素数量
for(E e : m.keySet())
s.writeObject(e);
//遍历操作,写出所有的元素
}
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException{
//读入操作
s.defaultReadObject();
//读入其他隐藏的东西
@SuppressWarnings("unchecked")
Comparator<? super E> c = (Comparator<? super E>)s.readObject();
//读入比较器
TreeMap<E,Object> tm = new TreeMap<>(c);
//创建一个新的TreeMap类
m = tm;
int size = s.readInt();
//读入TreeSet的大小
tm.readTreeSet(size,s,PRESENT);
//调用tm的方法读入元素并建树
}
public Spliterator<E> spliterator(){
//获得分割器
return TreeMap.keySpliteratorFor(m);
}
private static final long serialVersionUID = -2479143000061671589L;
//序列化标志,用于反序列化
}
参考资料: