JDK 8 TreeSet 源码详解(完整版带详细注释)

JDK 8 TreeSet 源码详解(完整版带详细注释)

1. 基本结构和常量定义

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable {
    
    // 序列化版本号
    private static final long serialVersionUID = -2479143000061671589L;
    
    // 底层使用TreeMap存储元素,元素作为TreeMap的key存储,value为PRESENT对象
    private transient NavigableMap<E,Object> m;
    
    // TreeMap中value的占位符对象,所有元素都使用这个相同的值
    private static final Object PRESENT = new Object();
}

2. 构造函数

/**
 * 无参构造函数
 * 构造一个空的TreeSet,元素按照自然排序进行排序
 */
public TreeSet() {
    this(new TreeMap<E,Object>());
}

/**
 * 指定比较器的构造函数
 * @param comparator 比较器,用于定义元素的排序规则
 */
public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator));
}

/**
 * 从集合构造TreeSet
 * @param c 要构造TreeSet的集合
 * @throws NullPointerException 如果集合为null
 */
public TreeSet(Collection<? extends E> c) {
    this();
    addAll(c);
}

/**
 * 从SortedSet构造TreeSet
 * @param s 要构造TreeSet的SortedSet
 */
public TreeSet(SortedSet<E> s) {
    this(s.comparator());
    addAll(s);
}

/**
 * 内部构造函数,用于初始化底层的NavigableMap
 * @param m 底层的NavigableMap
 */
TreeSet(NavigableMap<E,Object> m) {
    this.m = m;
}

3. 核心方法实现

3.1 add方法

/**
 * 添加元素到TreeSet中
 * @param e 要添加的元素
 * @return 如果元素不存在则添加并返回true,如果元素已存在则返回false
 */
public boolean add(E e) {
    // 调用NavigableMap的put方法,value始终为PRESENT对象
    // 如果返回null说明是新添加的元素,否则说明元素已存在
    return m.put(e, PRESENT) == null;
}

3.2 remove方法

/**
 * 从TreeSet中移除指定元素
 * @param o 要移除的元素
 * @return 如果元素存在并被移除返回true,否则返回false
 */
public boolean remove(Object o) {
    // 调用NavigableMap的remove方法,如果返回PRESENT说明元素存在并被移除
    return m.remove(o) == PRESENT;
}

3.3 contains方法

/**
 * 判断TreeSet是否包含指定元素
 * @param o 要查找的元素
 * @return 如果包含返回true,否则返回false
 */
public boolean contains(Object o) {
    // 调用NavigableMap的containsKey方法
    return m.containsKey(o);
}

3.4 size和isEmpty方法

/**
 * 返回TreeSet中元素的数量
 */
public int size() {
    return m.size();
}

/**
 * 判断TreeSet是否为空
 */
public boolean isEmpty() {
    return m.isEmpty();
}

3.5 clear方法

/**
 * 清空TreeSet中的所有元素
 */
public void clear() {
    m.clear();
}

4. 排序相关方法

4.1 比较器方法

/**
 * 获取比较器
 * @return 比较器,如果使用自然排序则返回null
 */
public Comparator<? super E> comparator() {
    return m.comparator();
}

4.2 首尾元素方法

/**
 * 获取第一个(最小)元素
 * @return 第一个元素
 * @throws NoSuchElementException 如果TreeSet为空
 */
public E first() {
    return m.firstKey();
}

/**
 * 获取最后一个(最大)元素
 * @return 最后一个元素
 * @throws NoSuchElementException 如果TreeSet为空
 */
public E last() {
    return m.lastKey();
}

4.3 范围操作方法

/**
 * 获取并移除第一个元素
 * @return 第一个元素
 * @throws NoSuchElementException 如果TreeSet为空
 */
public E pollFirst() {
    Map.Entry<E,?> e = m.pollFirstEntry();
    return (e == null) ? null : e.getKey();
}

/**
 * 获取并移除最后一个元素
 * @return 最后一个元素
 * @throws NoSuchElementException 如果TreeSet为空
 */
public E pollLast() {
    Map.Entry<E,?> e = m.pollLastEntry();
    return (e == null) ? null : e.getKey();
}

5. 导航方法(NavigableSet接口)

5.1 下一个/上一个元素

/**
 * 返回严格小于给定元素的最大元素
 * @param e 给定元素
 * @return 严格小于给定元素的最大元素,如果不存在返回null
 */
public E lower(E e) {
    return m.lowerKey(e);
}

/**
 * 返回小于或等于给定元素的最大元素
 * @param e 给定元素
 * @return 小于或等于给定元素的最大元素,如果不存在返回null
 */
public E floor(E e) {
    return m.floorKey(e);
}

/**
 * 返回大于或等于给定元素的最小元素
 * @param e 给定元素
 * @return 大于或等于给定元素的最小元素,如果不存在返回null
 */
public E ceiling(E e) {
    return m.ceilingKey(e);
}

/**
 * 返回严格大于给定元素的最小元素
 * @param e 给定元素
 * @return 严格大于给定元素的最小元素,如果不存在返回null
 */
public E higher(E e) {
    return m.higherKey(e);
}

5.2 子集操作

/**
 * 返回此set的部分视图,其元素范围从fromElement到toElement
 * @param fromElement 起始元素(包含)
 * @param toElement 结束元素(不包含)
 * @return 指定范围的子集
 */
public SortedSet<E> subSet(E fromElement, E toElement) {
    return new TreeSet<>(m.subMap(fromElement, true, toElement, false));
}

/**
 * 返回此set的部分视图,其元素小于toElement
 * @param toElement 结束元素(不包含)
 * @return 小于指定元素的子集
 */
public SortedSet<E> headSet(E toElement) {
    return new TreeSet<>(m.headMap(toElement, false));
}

/**
 * 返回此set的部分视图,其元素大于或等于fromElement
 * @param fromElement 起始元素(包含)
 * @return 大于或等于指定元素的子集
 */
public SortedSet<E> tailSet(E fromElement) {
    return new TreeSet<>(m.tailMap(fromElement, true));
}

/**
 * 返回此set的部分视图,其元素范围从fromElement到toElement
 * @param fromElement 起始元素
 * @param fromInclusive 是否包含起始元素
 * @param toElement 结束元素
 * @param toInclusive 是否包含结束元素
 * @return 指定范围的子集
 */
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
                              E toElement,   boolean toInclusive) {
    return new TreeSet<>(m.subMap(fromElement, fromInclusive,
                                  toElement,   toInclusive));
}

/**
 * 返回此set的部分视图,其元素小于(或等于)toElement
 * @param toElement 结束元素
 * @param inclusive 是否包含结束元素
 * @return 小于(或等于)指定元素的子集
 */
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
    return new TreeSet<>(m.headMap(toElement, inclusive));
}

/**
 * 返回此set的部分视图,其元素大于(或等于)fromElement
 * @param fromElement 起始元素
 * @param inclusive 是否包含起始元素
 * @return 大于(或等于)指定元素的子集
 */
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
    return new TreeSet<>(m.tailMap(fromElement, inclusive));
}

5.3 反向操作

/**
 * 返回此set的逆序视图
 * @return 逆序视图
 */
public NavigableSet<E> descendingIterator() {
    return m.descendingKeySet();
}

6. 迭代器实现

/**
 * 返回迭代器(按升序)
 */
public Iterator<E> iterator() {
    return m.navigableKeySet().iterator();
}

/**
 * 返回逆序迭代器(按降序)
 */
public Iterator<E> descendingIterator() {
    return m.descendingKeySet().iterator();
}

7. 其他重要方法

7.1 toArray方法

/**
 * 返回包含所有元素的数组
 */
public Object[] toArray() {
    return m.keySet().toArray();
}

/**
 * 返回包含所有元素的指定类型数组
 */
public <T> T[] toArray(T[] a) {
    return m.keySet().toArray(a);
}

7.2 clone方法

/**
 * 克隆方法
 */
@SuppressWarnings("unchecked")
public Object clone() {
    TreeSet<E> newSet = new TreeSet<>(m.comparator());
    newSet.addAll(this);
    return newSet;
}

7.3 Spliterator方法(Java 8新增)

/**
 * 返回Spliterator(用于并行流操作)
 */
public Spliterator<E> spliterator() {
    return m.keySet().spliterator();
}

8. 总结

8.1 TreeSet的特点

  1. 底层实现:基于TreeMap实现,元素作为TreeMap的key存储
  2. 有序性:保持元素的排序顺序(自然排序或自定义比较器)
  3. 唯一性:不允许存储重复元素
  4. 不允许null:如果使用自然排序,元素不能为null
  5. 非线程安全:不是线程安全的
  6. 高性能:基本操作(add、remove、contains)时间复杂度为O(log n)

8.2 时间复杂度分析

  • 添加元素:O(log n)
  • 删除元素:O(log n)
  • 查找元素:O(log n)
  • 遍历元素:O(n)
  • 范围查询:O(log n + k),k为结果集大小

8.3 空间复杂度

  • 存储空间:O(n) - n为存储的元素个数
  • 额外空间:TreeMap需要额外的存储空间(红黑树结构)

8.4 TreeSet与TreeMap的关系

// TreeSet内部结构示意图:
// TreeSet中的元素e <--> TreeMap中的键值对(e, PRESENT)
// 其中PRESENT是一个共享的Object实例

8.5 使用建议

  1. 适用场景

    • 需要去除重复元素并保持排序
    • 需要快速查找元素是否存在
    • 需要频繁进行范围查询
    • 需要找到最小/最大元素
  2. 不适用场景

    • 不需要排序功能(考虑使用HashSet)
    • 需要快速随机访问(考虑使用ArrayList)
    • 多线程环境(考虑使用Collections.synchronizedSortedSet()包装)
  3. 性能优化

    • 确保元素的compareTo()或比较器实现正确
    • 选择合适的元素类型以获得良好的排序性能
    • 对于大量数据的批量操作,可以考虑使用addAll()方法

8.6 关键设计思想

  1. 委托模式:TreeSet将大部分操作委托给内部的NavigableMap实现
  2. 占位符模式:使用固定的PRESENT对象作为TreeMap的value
  3. 适配器模式:将Map接口适配为Set接口
  4. 导航功能:实现了NavigableSet接口,提供丰富的导航方法

8.7 与其他Set实现的比较

特性HashSetLinkedHashSetTreeSet
底层实现HashMapLinkedHashMapTreeMap
时间复杂度O(1)O(1)O(log n)
空间复杂度O(n)O(n)O(n)
排序无序插入顺序自然排序/自定义排序
null元素允许一个允许一个不允许(自然排序时)
适用场景一般用途需要保持插入顺序需要排序

TreeSet的设计体现了面向对象设计的精髓:简单、高效、易于理解和维护。通过组合TreeMap,TreeSet获得了优秀的排序功能和性能表现,同时保持了代码的简洁性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值