集合源码分析(五)TreeSet集合

1、TreeSet概述:

TreeSet是Set的一个子类,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的。

2、TreeSet集合存储Integer和String:

TreeSet<String> ts = new TreeSet<>();            |            TreeSet<Integer> ts = new TreeSet<>();
    ts.add("q");                                                    |                ts.add(5);
    ts.add("q");                                                    |                ts.add(4);
    ts.add("w");                                                   |                ts.add(1);
    ts.add("e");                                                    |                ts.add(3);
    ts.add("r");                                                     |                ts.add(2);
    ts.add("d");                                                    |                ts.add(7);
    ts.add("f");                                                     |                ts.add(7);
    System.out.println(ts);                                   |               System.out.println(ts);
//[d, e, f, q, r, w]                                                 |                //[1, 2, 3, 4, 5, 7]
//去重,排序。    字典顺序                                |                //去重,排序。升序

3、TreeSet 保证顺序的原理:

要指定一个顺序让 TreeSet 去按照这个顺序去排列        
        TreeSet 是一个容器,只不过这个容器有一个特殊的作用,就是排序。
                但是排序的时候我们需要制定一种顺序去排。
                所以TreeSet集合我们只需要研究他是怎么排。

第一种排序方式:
            自然排序:让元素具有比较性       

 public class Person implements Comparable<Person>{
        @Override
        public int compareTo(Person o) {
           return this.age - o.age;
        }
}

 //其中this 表示现在正在往里面存的这个元素
 //o表示二叉树结构中正在要比较的那个元素。

        
        TreeSet<Person> ts = new TreeSet<>();
        ts.add(new Person("zhangsan",11));
        ts.add(new Person("zhangsan",10));
        ts.add(new Person("zhangsan",14));
        ts.add(new Person("zhangsan",12));
        ts.add(new Person("zhangsan",13));
        打印结果,按照年龄比较。
    
    TreeSet 集合跟HashCode方法 equals方法无关。第一种排序只看compareTo的返回值
        如果返回0,不存//认为是一样的
        如果返回负数//存储在左边
        如果返回正数//存储在右边

第二种排序方式:
            比较器排序:给集合传递一个比较的规则。   

TreeSet<Person> ts = new TreeSet<>(new Comparator<Person>() {
	@Override
	public int compare(Person o1, Person o2) {
		return o1.getAge() - o2.getAge();
	}
});
ts.add(new Person("zhangsan",11));
ts.add(new Person("zhangsan",10));
ts.add(new Person("zhangsan",14));
ts.add(new Person("zhangsan",12));
ts.add(new Person("zhangsan",13));
System.out.println(ts);

//其中o1表示现在正在往里面存的这个元素
//o2表示二叉树结构中正在要比较的那个元素。
         
    TreeSet 集合跟HashCode方法 equals方法无关。第二种排序只看compare的返回值
        如果返回0,不存//认为是一样的
        如果返回负数//存储在左边
        如果返回正数//存储在右边
如果两种排序都存在,那么以第二种为准。第一种都不会去调用。
    我们实际开发的时候,默认使用第一种。 在第一种满足不了要求的时候。此时按照第二种排。

    比如String。JAVA 默认使用字典顺序进行排序。现在要求要按照字符串的长度进行排序。 我们不能直接修改JAVA里面的源码。只能使用第二种排序方式了。当我们无法修改第一种排序规则的时候,使用第二种排序规则。

4、TreeSet和HashSet的区别:

1、HashSet和TreeSet都是Set接口的实现类。

2、HashSet并不会对集合中的内容进行排序,根据对象的哈希值进行存放。

3、TreeSet 中的对象必须是Comparable(实现Comparable接口)按照对象中重写compareTo方法中的比较结果进行存放。

猜你喜欢

转载自blog.csdn.net/MyronCham/article/details/82897814