Java - TreeSet源码解析

Posted qlky

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java - TreeSet源码解析相关的知识,希望对你有一定的参考价值。

Java提高篇(二八)------TreeSet

 

与HashSet是基于HashMap实现一样,TreeSet同样是基于TreeMap实现的。在《Java提高篇(二七)-----TreeMap》中LZ详细讲解了TreeMap实现机制,如果客官详情看了这篇博文或者多TreeMap有比较详细的了解,那么TreeSet的实现对您是喝口水那么简单。

一、TreeSet定义

我们知道TreeMap是一个有序的二叉树,那么同理TreeSet同样也是一个有序的,它的作用是提供有序的Set集合。通过源码我们知道TreeSet基础AbstractSet,实现NavigableSet、Cloneable、Serializable接口。其中AbstractSet提供 Set 接口的骨干实现,从而最大限度地减少了实现此接口所需的工作。NavigableSet是扩展的 SortedSet,具有了为给定搜索目标报告最接近匹配项的导航方法,这就意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。Cloneable支持克隆,Serializable支持序列化。

public class TreeSet<E> extends AbstractSet<E>    implements NavigableSet<E>, Cloneable, java.io.Serializable

同时在TreeSet中定义了如下几个变量。

private transient NavigableMap<E,Object> m;        //PRESENT会被当做Map的value与key构建成键值对 
private static final Object PRESENT = new Object();

其构造方法

// 默认构造函数。使用该构造函数,TreeSet中的元素按照自然排序进行排列。
TreeSet()

// 创建的TreeSet包含collection
TreeSet(Collection<? extends E> collection)

// 指定TreeSet的比较器
TreeSet(Comparator<? super E> comparator)

// 创建的TreeSet包含set
TreeSet(SortedSet<E> set)

 

二、TreeSet主要方法

1、add:将指定的元素添加到此 set(如果该元素尚未存在于 set 中)。

public boolean add(E e) {        return m.put(e, PRESENT)==null;    }

TreeSet的API

boolean                   add(E object)
boolean                   addAll(Collection<? extends E> collection)
void                      clear()
Object                    clone()
boolean                   contains(Object object)
E                         first()
boolean                   isEmpty()
E                         last()
E                         pollFirst()
E                         pollLast()
E                         lower(E e)
E                         floor(E e)
E                         ceiling(E e)
E                         higher(E e)
boolean                   remove(Object object)
int                       size()
Comparator<? super E>     comparator()
Iterator<E>               iterator()
Iterator<E>               descendingIterator()
SortedSet<E>              headSet(E end)
NavigableSet<E>           descendingSet()
NavigableSet<E>           headSet(E end, boolean endInclusive)
SortedSet<E>              subSet(E start, E end)
NavigableSet<E>           subSet(E start, boolean startInclusive, E end, boolean endInclusive)
NavigableSet<E>           tailSet(E start, boolean startInclusive)
SortedSet<E>              tailSet(E start)

说明

(01) TreeSet是有序的Set集合,因此支持add、remove、get等方法。
(02) 和NavigableSet一样,TreeSet的导航方法大致可以区分为两类,一类时提供元素项的导航方法,返回某个元素;另一类时提供集合的导航方法,返回某个集合。
lower、floor、ceiling 和 higher 分别返回小于、小于等于、大于等于、大于给定元素的元素,如果不存在这样的元素,则返回 null。

 

TreeSet不支持快速随机遍历,只能通过迭代器进行遍历!

 

TreeSet遍历测试程序如下:

import java.util.*;

/**
 * @desc TreeSet的遍历程序
 *
 * @author skywang
 * @email kuiwu-wang@163.com
 */
public class TreeSetIteratorTest {

    public static void main(String[] args) {
        TreeSet set = new TreeSet();
        set.add("aaa");
        set.add("aaa");
        set.add("bbb");
        set.add("eee");
        set.add("ddd");
        set.add("ccc");

        // 顺序遍历TreeSet
        ascIteratorThroughIterator(set) ;
        // 逆序遍历TreeSet
        descIteratorThroughIterator(set);
        // 通过for-each遍历TreeSet。不推荐!此方法需要先将Set转换为数组
        foreachTreeSet(set);
    }

    // 顺序遍历TreeSet
    public static void ascIteratorThroughIterator(TreeSet set) {
        System.out.print("\\n ---- Ascend Iterator ----\\n");
        for(Iterator iter = set.iterator(); iter.hasNext(); ) {
            System.out.printf("asc : %s\\n", iter.next());
        }
    }

    // 逆序遍历TreeSet
    public static void descIteratorThroughIterator(TreeSet set) {
        System.out.printf("\\n ---- Descend Iterator ----\\n");
        for(Iterator iter = set.descendingIterator(); iter.hasNext(); )
            System.out.printf("desc : %s\\n", (String)iter.next());
    }

    // 通过for-each遍历TreeSet。不推荐!此方法需要先将Set转换为数组
    private static void foreachTreeSet(TreeSet set) {
        System.out.printf("\\n ---- For-each ----\\n");
        String[] arr = (String[])set.toArray(new String[0]);
        for (String str:arr)
            System.out.printf("for each : %s\\n", str);
    }
}

 

 

三、最后

由于TreeSet是基于TreeMap实现的,所以如果我们对treeMap有了一定的了解,对TreeSet那是小菜一碟,我们从TreeSet中的源码可以看出,其实现过程非常简单,几乎所有的方法实现全部都是基于TreeMap的。

 

以上是关于Java - TreeSet源码解析的主要内容,如果未能解决你的问题,请参考以下文章

java 17 - 6 TreeSet集合及其add()方法的源码解析

#yyds干货盘点# Map - TreeSet & TreeMap 源码解析

Java集合--TreeSet详细解析

java集合Set集合之TreeSet详解

TreeSet源码解析笔记

TreeSet和TreeMap部分源码解析