TreeSet简介

  TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, java.io.Serializable接口。
  TreeSet 继承于AbstractSet,所以它是一个Set集合,具有Set的属性和方法。
  TreeSet 实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。
  TreeSet 实现了Cloneable接口,意味着它能被克隆。
  TreeSet 实现了java.io.Serializable接口,意味着它支持序列化。

  TreeSet是基于TreeMap实现的。TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。
  TreeSet为基本操作(add、remove 和 contains)提供受保证的 log(n) 时间开销。
  另外,TreeSet是非同步的。 它的iterator 方法返回的迭代器是fail-fast的。

TreeSet的构造函数

// 默认构造函数。使用该构造函数,TreeSet中的元素按照自然排序进行排列。
TreeSet() // 创建的TreeSet包含collection
TreeSet(Collection<? extends E> collection) // 指定TreeSet的比较器
TreeSet(Comparator<? super E> comparator) // 创建的TreeSet包含set
TreeSet(SortedSet<E> set)

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而言,它是基于TreeMap实现的,TreeSet底层使用TreeMap来保存所有元素,因此TreeSet的实现比较简单,相关TreeSet的操作,基本上都是直接调用底层TreeMap的相关方法来完成,
  TreeSet的源代码如下:

/*
* @(#)TreeSet.java 1.37 06/05/10
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/ package java.util; /**
* @param <E> the type of elements maintained by this set
*
* @author Josh Bloch
* @version 1.37, 05/10/06
* @see Collection
* @see Set
* @see HashSet
* @see Comparable
* @see Comparator
* @see TreeMap
* @since 1.2
*/ public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
/**
* NavigableMap对象
*/
private transient NavigableMap<E,Object> m; // TreeSet是通过TreeMap实现的,
// PRESENT是键-值对中的值。
private static final Object PRESENT = new Object(); /**
* 将TreeMap赋值给 "NavigableMap对象m"
*/
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
} /**
* 不带参数的构造函数。创建一个空的TreeMap
*/
public TreeSet() {
this(new TreeMap<E,Object>());
} /**
* 带比较器的构造函数。
*/
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<E,Object>(comparator));
} /**
* 创建TreeSet,并将集合c中的全部元素都添加到TreeSet中
*/
public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
} /**
* 创建TreeSet,并将s中的全部元素都添加到TreeSet中
*/
public TreeSet(SortedSet<E> s) {
this(s.comparator());
addAll(s);
} /**
* 返回TreeSet的顺序排列的迭代器。
* 因为TreeSet是TreeMap实现的,所以这里实际上时返回TreeMap的“键集”对应的迭代器
*/
public Iterator<E> iterator() {
return m.navigableKeySet().iterator();
} /**
* 返回TreeSet的逆序排列的迭代器。
* 因为TreeSet是TreeMap实现的,所以这里实际上时返回TreeMap的“键集”对应的迭代器
*/
public Iterator<E> descendingIterator() {
return m.descendingKeySet().iterator();
} /**
* 返回NavigableSet<E>类型的TreeSet
*/
public NavigableSet<E> descendingSet() {
return new TreeSet(m.descendingMap());
} /**
* 返回大小
*/
public int size() {
return m.size();
} /**
* 是否为空
*/
public boolean isEmpty() {
return m.isEmpty();
} /**
* 是否包含o
*/
public boolean contains(Object o) {
return m.containsKey(o);
} /**
* 添加元素e
*/
public boolean add(E e) {
return m.put(e, PRESENT)==null;
} /**
* 删除元素o
*/
public boolean remove(Object o) {
return m.remove(o)==PRESENT;
} /**
* 清空集合
*/
public void clear() {
m.clear();
} /**
* 将集合c中的全部元素添加到TreeSet中
*/
public boolean addAll(Collection<? extends E> c) {
// Use linear-time version if applicable
if (m.size()==0 && c.size() > 0 &&
c instanceof SortedSet &&
m instanceof TreeMap) {
SortedSet<? extends E> set = (SortedSet<? extends E>) c;
TreeMap<E,Object> map = (TreeMap<E, Object>) m;
Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
Comparator<? super E> mc = map.comparator();
if (cc==mc || (cc != null && cc.equals(mc))) {
map.addAllForTreeSet(set, PRESENT);
return true;
}
}
return super.addAll(c);
} /**
* 返回子Set,实际上是通过TreeMap的subMap()实现的。
*/
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive) {
return new TreeSet<E>(m.subMap(fromElement, fromInclusive,
toElement, toInclusive));
} /**
* 返回Set的头部,范围是:从头部到toElement。
* inclusive是是否包含toElement的标志
*/
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
return new TreeSet<E>(m.headMap(toElement, inclusive));
} /**
* 返回Set的尾部,范围是:从fromElement到结尾。
* inclusive是是否包含fromElement的标志
*/
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
return new TreeSet<E>(m.tailMap(fromElement, inclusive));
} /**
* 返回子Set。范围是:从fromElement(包括)到toElement(不包括)。
*/
public SortedSet<E> subSet(E fromElement, E toElement) {
return subSet(fromElement, true, toElement, false);
} /**
* 返回Set的头部,范围是:从头部到toElement(不包括)。
*/
public SortedSet<E> headSet(E toElement) {
return headSet(toElement, false);
} /**
* 返回Set的尾部,范围是:从fromElement到结尾(不包括)。
*/
public SortedSet<E> tailSet(E fromElement) {
return tailSet(fromElement, true);
} // 返回Set的比较器
public Comparator<? super E> comparator() {
return m.comparator();
} /**
* 返回Set的第一个元素
*/
public E first() {
return m.firstKey();
} /**
* 返回Set的最后一个元素
*/
public E last() {
return m.lastKey();
} // NavigableSet API methods /**
* 返回Set中小于e的最大元素
*/
public E lower(E e) {
return m.lowerKey(e);
} /**
* 返回Set中小于/等于e的最大元素
*/
public E floor(E e) {
return m.floorKey(e);
} /**
* 返回Set中大于/等于e的最小元素
*/
public E ceiling(E e) {
return m.ceilingKey(e);
} /**
* 返回Set中大于e的最小元素
*/
public E higher(E e) {
return m.higherKey(e);
} /**
* 获取第一个元素,并将该元素从TreeMap中删除。
*/
public E pollFirst() {
Map.Entry<E,?> e = m.pollFirstEntry();
return (e == null)? null : e.getKey();
} /**
* 获取最后一个元素,并将该元素从TreeMap中删除。
*/
public E pollLast() {
Map.Entry<E,?> e = m.pollLastEntry();
return (e == null)? null : e.getKey();
} /**
* 克隆一个TreeSet,并返回Object对象
*/
public Object clone() {
TreeSet<E> clone = null;
try {
clone = (TreeSet<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError();
} clone.m = new TreeMap<E,Object>(m);
return clone;
} /**
* java.io.Serializable的写入函数
*
* 将TreeSet的“比较器、容量,所有的元素值”都写入到输出流中
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden stuff
s.defaultWriteObject(); // 写入比较器
s.writeObject(m.comparator()); // 写入容量
s.writeInt(m.size()); // 写入“TreeSet中的每一个元素”
for (Iterator i=m.keySet().iterator(); i.hasNext(); )
s.writeObject(i.next());
} /**
* java.io.Serializable的读取函数:根据写入方式读出
* 先将TreeSet的“比较器、容量、所有的元素值”依次读出
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden stuff
s.defaultReadObject(); // 从输入流中读取TreeSet的“比较器”
Comparator<? super E> c = (Comparator<? super E>) s.readObject(); // Create backing TreeMap
TreeMap<E,Object> tm;
if (c==null)
tm = new TreeMap<E,Object>();
else
tm = new TreeMap<E,Object>(c);
m = tm; // 从输入流中读取TreeSet的“容量”
int size = s.readInt();
// 从输入流中读取TreeSet的“全部元素”
tm.readTreeSet(size, s, PRESENT);
}
// TreeSet的序列版本号
private static final long serialVersionUID = -2479143000061671589L;
}

总结:

(01) TreeSet实际上是TreeMap实现的。当我们构造TreeSet时;若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。
(02) TreeSet是非线程安全的。
(03) TreeSet实现java.io.Serializable的方式。当写入到输出流时,依次写入“比较器、容量、全部元素”;当读出输入流时,再依次读取。

Java集合源码分析(六)TreeSet<E>的更多相关文章

  1. java集合源码分析(六):HashMap

    概述 HashMap 是 Map 接口下一个线程不安全的,基于哈希表的实现类.由于他解决哈希冲突的方式是分离链表法,也就是拉链法,因此他的数据结构是数组+链表,在 JDK8 以后,当哈希冲突严重时,H ...

  2. java集合源码分析(三):ArrayList

    概述 在前文:java集合源码分析(二):List与AbstractList 和 java集合源码分析(一):Collection 与 AbstractCollection 中,我们大致了解了从 Co ...

  3. Java 集合源码分析(一)HashMap

    目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 Con ...

  4. Java集合源码分析(三)LinkedList

    LinkedList简介 LinkedList是基于双向循环链表(从源码中可以很容易看出)实现的,除了可以当做链表来操作外,它还可以当做栈.队列和双端队列来使用. LinkedList同样是非线程安全 ...

  5. Java集合源码分析(四)Vector<E>

    Vector<E>简介 Vector也是基于数组实现的,是一个动态数组,其容量能自动增长. Vector是JDK1.0引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是 ...

  6. Java集合源码分析(二)ArrayList

    ArrayList简介 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线 ...

  7. java集合源码分析几篇文章

    java集合源码解析https://blog.csdn.net/ns_code/article/category/2362915

  8. Java集合源码分析(十)——TreeSet

    简介 TreeSet就是一个集合,里面不能有重复的元素,但是元素是有序的. TreeSet其实就是调用了TreeMap实现的,所以,它也不是线程安全的.可以实现自然排序或者根据传入的Comparato ...

  9. Java集合源码分析(六)——ConcurrentHashMap

    目录 简介 源码分析 父类 接口 字段 内部类 1.链表节点结构 2.树根结构 3.树节点结构 方法 1.构造方法 2.基本并发方法 3.初始化表数组的操作 4.修改添加元素 5.统计元素数量 6.扩 ...

随机推荐

  1. Java正则表达式应用详解

    如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单.如果你不熟悉这个术语,那么“正则表达式”(Regular Expression)就是一个字 ...

  2. KendoUI系列:AutoComplete

    1.基本使用 <link href="@Url.Content("~/C ontent/kendo/2014.1.318/kendo.common.min.css" ...

  3. 最简单的SVN环境搭建过程

    本文简单描述最简单的SVN环境搭建过程 搭建环境:windows (个人验证了windows2003,windows xp) 使用软件:Setup-Subversion-1.6.17  //Serve ...

  4. bootstrap插件思路整理

    知识有时也需温故知新嘛,本次做一次bs插件梳理. $.support.transition 通过判断自定义元素是否支持WebkitTransition.MozTransition.OTransitio ...

  5. art-template用户注册方法

    应用场景nodejs Express框架,使用art-template模板引擎. 后台注册方法代码: var template = require('art-template'); template. ...

  6. 发表在 Science 上的一种新聚类算法

    今年 6 月份,Alex Rodriguez 和 Alessandro Laio 在 Science 上发表了一篇名为<Clustering by fast search and find of ...

  7. javascript学习8

    JavaScript 浏览器检测 实例 检测浏览器及版本 使用 JavaScript 检测关于访问者的浏览器名称及其版本. 检测浏览器的更多信息 使用 JavaScript 检测关于访问者浏览器的更多 ...

  8. Cannot override the final method from SherlockFragmentActivity

    调用ActionBarSherlock后页面找不到onCreateOptionsMenu报错 com.actionbarsherlock.app.SherlockFragmentActivity.on ...

  9. [Azure附录]2.在Windows Server 2012中配置AD域服务

    <Windows Azure Platform 系列文章目录> 本章我们配置的AD域名为contoso.com 1.安装完AD域服务后,我们返回服务器管理器界面,点击"将此服务器 ...

  10. C#根据身份证号码,计算生日、年龄、性别

    朋友谈及身份证相关的信息,才了解到原来省份证号码中包含了年龄和性别. 这样在数据库中,就不必单独留字段存放它们了(不过,要根据具体情况来,要是读取频率较高,还是单独列出为好),这样顺带解决了年龄变更的 ...