Java 集合框架系列十一:JDK 1.8 TreeSet 详解

TreeSet 继承关系

在这里插入图片描述

类文档解读

老规矩,先通过 TreeSet 的类文档了解一下能得到哪些信息。

  • TreeSet 是 JDK 1.2 提供的基于 TreeMap 的 NavigableSet 实现。
  • TreeSet 支持元素的自然排序和按照在创建时指定的 Comparator 比较器进行排序。
  • TreeSet 的基本操作(add、remove 和 contains)的时间复杂度是 log(n) 。
  • TreeSet 是非线程安全的。
  • TreeSet 的迭代器是 fail-fast 策略的。

TreeSet API

成员变量

	// 存储数据的底层数据结构
	private transient NavigableMap<E,Object> m;

    // 由于 TreeSet 只需要使用 Key 进行存储,因此 Value 存储的是一个虚拟值
    private static final Object PRESENT = new Object();

构造方法

TreeSet 底层使用的是 NavigableMap 存储数据,如果没有指定具体是 NavigableMap 的哪个实现类则默认使用 TreeMap 作为底层存储数据的结构。

    /**
     * 通过指定的 NavigableMap 创建实例
     */
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }

    /**
     * 使用 TreeMap 创建一个空的 TreeSet,使用自然排序,
     * 添加的元素需要实现 Comparable 接口,即是可比较的
     */
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

    /**
     * 指定比较器,如果比较器是 null 将使用自然排序
     */
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }
    
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    public TreeSet(SortedSet<E> s) {
        this(s.comparator());
        addAll(s);
    }
}

其他API

TreeSet 对元素的操作基本都是调用 NavigableMap 的方法进行操作。

	public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
	public boolean remove(Object o) {
        return m.remove(o)==PRESENT;
    }
    public boolean contains(Object o) {
        return m.containsKey(o);
    }
	public E pollFirst() {
        Map.Entry<E,?> e = m.pollFirstEntry();
        return (e == null) ? null : e.getKey();
    }

总结

  • TreeSet 里添加的元素必须是同一类型的。
  • 当向 TreeSet 内添加对象时,可以有两种排序方法:
    • 自然排序,如 String、包装类默认按照从小到大的顺序遍历。
    • 定制排序。
自然排序

TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序排列。如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。实现 Comparable 的类必须重写 compareTo(Object obj) 方法,两个对象通过 compareTo(Object obj) 方法的返回值来比较大小。

当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 时,应保证与 compareTo(Object obj) 方法有一致的结果:如果两个对象通过 equals() 方法比较返回 true,则通过 compareTo(Object obj) 方法比较应返回 0,要求 equals() 方法和 hashCode() 方法和 compareTo() 方法保持一致。

定制排序

TreeSet 的自然排序是根据集合元素的大小,进行元素升序排列。如果需要定制排序,比如降序排列,可借助 Comparator 接口的帮助。需要重写 compare(T o1,T o2) 方法。利用 int compare(T o1,T o2) 方法,比较 o1 和 o2 的大小:如果方法返回正整数,则表示 o1 大于 o2;如果返回 0 表示相等;返回负整数 表示 o1 小于 o2。要实现定制排序,需要将实现 Comparator 接口的实例作为形参传递给 TreeSet 的构造器。此时仍然只能向 TreeSet 中添加类型相同的对象否则发生 ClassCastException 异常。使用定制排序判断两个元素相等的标准是:通过 Comparator 比较两个元素返回了 0,要求 equals() 方法和 hashCode() 方法和 compareTo() 方法保持一致。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值