Java 集合之TreeSet 自定义类 比较器

Java 集合之TreeSet

  • 基于 TreeMap 的 NavigableSet 实现。 使用元素的自然顺序进行排序,或者通过在集合创建时提供的 Comparator 进行排序,具体取决于使用的构造函数。唯一,无序(没有按照输入顺序进行输出)又有序(按照升序进行遍历)。

  • 此实现为基本操作(添加、删除和包含)提供有保证的 log(n) 时间成本。

  • 请注意,如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。 (请参阅 Comparable 或 Comparator 以获取与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但是 TreeSet 实例使用它的 compareTo(或 compare)方法执行所有元素比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。 即使它的顺序与 equals 不一致,set 的行为是明确定义的; 它只是不遵守 Set 接口的一般约定。

  • 请注意,此实现不是同步的。 如果多个线程同时访问一个 TreeSet,并且至少有一个线程修改了 set,则必须在外部进行同步。 这通常是通过同步一些自然封装集合的对象来实现的。 如果不存在此类对象,则应使用 Collections.synchronizedSortedSet 方法“包装”该 set。 这最好在创建时完成,以防止对集合的意外不同步访问:SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

  • 此类的 iterator 方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间修改set,除了通过迭代器自己的 remove 方法以外的任何方式,迭代器都会抛出 ConcurrentModificationException。 因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。

  • 请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。 快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。 因此,编写依赖于此异常的程序的做法是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测 bug。

  • TreeSet底层的二叉树的遍历是按照升序的结果出现的,这个升序由中序遍历得到。

构造函数

  • TreeSet()

    • 构造一个新的空树集,根据其元素的自然顺序进行排序。
  • TreeSet (Collection<? extends E> c)

    • 构造一个包含指定collection 元素的新 TreeSet,根据其元素的自然顺序进行排序。
  • TreeSet (Comparator<? super E> Comparator)

    • 构造一个新的空TreeSet,根据指定的比较器进行排序。
  • TreeSet (SortedSet s)

    • 构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。

方法

Modifier and TypeMethodDescription
booleanadd (E e)如果指定元素尚不存在,则将其添加到此集合中。
booleanaddAll (Collection<? extends E> c)将指定 collection 中的所有元素添加到此 set 中。
Eceiling(E e)返回此集合中大于或等于给定元素的最小元素,如果没有这样的元素,则返回 null。
voidclear()从此集合中删除所有元素。
Objectclone()返回此 TreeSet 实例的浅表副本。
Comparator<? super E>comparator()返回用于对该集合中的元素进行排序的比较器,如果该集合使用其元素的自然排序,则返回 null。
booleancontains (Object o)如果此集合包含指定的元素,则返回 true。
IteratordescendingIterator()以降序返回此集合中元素的迭代器。
NavigableSetdescendingSet()返回此集合中包含的元素的逆序视图。
Efirst()返回当前在此集合中的第一个(最低)元素。
Efloor (E e)返回该集合中小于或等于给定元素的最大元素,如果没有这样的元素,则返回 null。
SortedSetheadSet (E toElement)返回此集合中元素严格小于 toElement 的部分的视图。
NavigableSetheadSet (E toElement, boolean inclusive)返回此集合中元素小于(或等于,如果 inclusive 为真)toElement 的部分的视图。
Ehigher(E e)返回此集合中严格大于给定元素的最小元素,如果没有这样的元素,则返回 null。
booleanisEmpty()如果此集合不包含任何元素,则返回 true。
Iteratoriterator()以升序返回此集合中元素的迭代器。
Elast()返回当前在此集合中的最后一个(最高)元素。
Elower (E e)返回此集合中严格小于给定元素的最大元素,如果没有这样的元素,则返回 null。
EpollFirst()检索并删除第一个(最低)元素,如果此集合为空,则返回 null。
EpollLast()检索并删除最后一个(最高)元素,如果此集合为空,则返回 null。
booleanremove (Object o)如果指定的元素存在,则从该集合中移除该元素。
intsize()返回此集合中的元素数(set 的容量)。
Spliteratorspliterator()在此集合中的元素上创建一个后期绑定和快速失败的 Spliterator。
SortedSetsubSet (E fromElement, E toElement)返回此集合中元素范围从 fromElement(含)到 toElement(不含)的部分的视图。
SortedSettailSet (E fromElement)返回此集合中元素大于或等于 fromElement 的部分的视图。
NavigableSettailSet (E fromElement, boolean inclusive)返回此集合中元素大于(或等于,如果 inclusive 为真)fromElement 的部分的视图。
  • NavigableSet subSet (E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
    • fromElement- 返回 set 的低端点,fromInclusive- 如果低端点要包含在返回的视图中,则为 true
      toElement- 返回 set 的高端点,toInclusive - 如果高端点要包含在返回的视图中,则为 true
    • 返回此 set 的部分视图,其元素范围从 fromElement 到 toElement。
    • 如果 fromElement 和 toElement 相等,则返回的 set 为空,除非 fromExclusive 和 toExclusive 都为 true。
    • 返回的 set 受此 set 支持,所以在返回 set 中的更改将反映在此 set 中,反之亦然。返回 set 支持此 set 支持的所有可选 set 操作。 如果试图在返回 set 的范围之外插入元素,则返回的 set 将抛出 IllegalArgumentException。

实例

整数型

//创建一个整数型TreeSet:
TreeSet<Integer> tsi = new TreeSet<>();
tsi.add(12);
tsi.add(3);
tsi.add(7);
tsi.add(9);
tsi.add(3);
tsi.add(16);
System.out.println(tsi.size()); //5
System.out.println(tsi); //[3, 7, 9, 12, 16]

在这里插入图片描述

String类型

//创建一个String类型TreeSet:
TreeSet<String> tss = new TreeSet<>();
tss.add("afyz");
tss.add("bfyz");
tss.add("afyz");
tss.add("dfyz");
System.out.println(tss.size()); //3
System.out.println(tss); //[afyz, bfyz, dfyz]

自定义类

内部比较器

自定义类可以通过Comparable接口自主决定存入数据时的比较内容

public class Student implements Comparable<Student> {
    private int age;
    private String name;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    @Override
    public int compareTo(Student o) { //比较器,比较时仅仅比较Age
        return this.getAge()-o.getAge();
    }
}

class TestST {
    public static void main(String[] args) {
        //创建一个Student类型TreeSet:
        TreeSet<Student> ts = new TreeSet<>();
        ts.add(new Student(1,"fyz"));
        ts.add(new Student(8,"fyz"));
        ts.add(new Student(6,"yjk"));
        ts.add(new Student(8,"fyz"));
        System.out.println(ts.size());
        System.out.println(ts);
    }
}
外部比较器
public class StudentOCT {
    public static void main(String[] args) {

        Comparator<Student> scpnt = new SCPN();//利用外部比较器,必须自己制定:
//        TreeSet<Student> ts = new TreeSet<>(scpnt);//一旦指定外部比较器,那么就会按照外部比较器来比较

        TreeSet<Student> ts = new TreeSet<>(new Comparator<Student>() { //匿名内部类
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });//一旦指定外部比较器,那么就会按照外部比较器来比较

        ts.add(new Student(1,"fyz"));
        ts.add(new Student(8,"fyz"));
        ts.add(new Student(6,"yjk"));
        ts.add(new Student(8,"fyz"));
        System.out.println(ts.size()); //2
        System.out.println(ts); //[Student{age=1, name='fyz'}, Student{age=6, name='yjk'}]
    }
}


class SCPN implements Comparator<Student> { //外部比较类
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getName().compareTo(o2.getName());
    }
}
posted @ 2021-08-18 13:59  SKPrimin  阅读(345)  评论(0编辑  收藏  举报