• 黑马程序员_集合学习之treeSet


    TreeSet与HashSet

    由于内部数据结构不同,判断元素重复的条件也不同,

    HashSet是判断元素的hashCode值是否相同,如果相同,还会继续判断元素的equals是否为真。

    TreeSet

    我们用如下的例子体现:

    TreeSet<String>ts = new TreeSet<String>();

          

           ts.add("aaa");

          

           ts.add("ddd");

           ts.add("eee");

           ts.add("bbb");

          

          

           for(Strings:ts)

           {

               System.out.println(s);

           }

    结果:

    aaa

    bbb

    ddd

    eee

    说明TreeSet可以按一定顺序(自然的顺序)进行排序。这也是它最大的特点。

    之后存一些自定义的对象。

    classStudent

    {

        privateStringname;

        privateintage;

        publicStudent(String name,int age) {

           super();

           this.name =name;

           this.age =age;

        }

        publicString getName() {

           returnname;

        }

        publicvoidsetName(String name) {

           this.name =name;

        }

        publicintgetAge() {

           returnage;

        }

        publicvoidsetAge(int age) {

           this.age =age;

        }

       

    }

    TreeSet<Student>ts = new TreeSet<Student>();

           ts.add(newStudent("001",1));

           ts.add(newStudent("003",2));

           ts.add(newStudent("002",3));

           ts.add(newStudent("004",4));

    运行抛出异常。

    原因是这个对象不具备比较性。

    。。。。

    TreeSet要求存入的元素具有比较性,怎么才能有比较性?

    要 实现一个comparable接口。并实现其中的方法。就具有了比较性。

     

    把相应的方法加入到student中

    publicintcompareTo(Object o)

        {

           Student s = (Student)o;

           System.out.println(this.name+"compareTo"+s.name);

          

          

          

            returnthis.age-s.age;

        }

        publicString toString()

        {

           returnthis.name+"..."+this.age;

        }

    再一次的调用

    TreeSet<Student>ts = new TreeSet<Student>();

           ts.add(newStudent("001",1));

           ts.add(newStudent("003",2));

           ts.add(newStudent("002",3));

           ts.add(newStudent("004",4));

          

           System.out.println(ts);

     

    输出

    003compareTo001

    002compareTo001

    002compareTo003

    004compareTo003

    004compareTo002

    [001...1,003...2, 002...3, 004...4]

    则说明正好是treeset底层调用了比较函数去进行了一系列的比较。

    并最终排好了序(根据compareTo中特殊的比较方式排序)。。

    但是。当出现

    ts.add(newStudent("009",4));

    时候,由于年龄一致

    所以输出

    [001...1,003...2, 002...3, 004...4]

    009没有被存入。

    所以必须要判断一下姓名。

     

    publicintcompareTo(Object o)

        {

           Student s = (Student)o;

           System.out.println(this.name+"compareTo"+s.name);

          

           if(this.age==s.age)

             return this.name.compareTo(s.name);

          

            returnthis.age-s.age;

        }

    这样,只有年龄和姓名一致后,才不被存入集合中,当年龄不一样时候,用年龄排序

    当年龄一致。则使用姓名进行排序。

     

    则输出

     

    [001...1,003...2, 002...3, 004...4, 009...4]

     

     

    所以要记住,在对自定义的对象排序时候,先对主要条件进行排序后,再对次要条件进行排序。

    下面,我们来看一看treeSet的内部实现机制。

    底层使用了一个特殊的数据结构。

    就使用上边的例子





    
    

    上述图的得出分析


    4存入,

    2进来,与4进行比较,小于4,放在左边。

    3进来,与4比较,在左,与2比较,大于2,故放在2的右边

    1进来,与4比较,在左,与2比较,小于2,故放在2的左边。

    也就是底层实现了一个二叉树。从而避免了加入一个元素的时候和集合中的每个元素

    进行比较。提高了比较 性能。

    那么如何进行取元素呢?

    按照定义的比较顺序去取,比如从小到大。

    那么先去左子树的最左边的值。往上依次走。

    有一个问题,想要是元素按原来的排序逆序输出呢?千万不要用

       returnthis.age-s.age;置换这里的thiss

    而是用java中有其他的特殊的方式去实现。

     

     

    对于TreeSet来说,它只用compareTo去看是负数,0,正数,而与其他方法无关。

     始终使用默认的比较的(小----->大)去存储和输出数据。

    也就是无论使用什么比较方式,都是按其比较的最小------》最大去对元素进行排序。

    也就是从二叉树的最左端到二叉树的最右端进行比较。

    综上所述:

    TreeSet可以对set集合中的元素进行排序。底层的数据结构是二叉树。保证元素唯一性的依据叫做compareTo()方法return 0;与hashcode没有关系。与equals也没有关系。TreeSet排序的第一种方式,让元素自身具备了比较性。元素需要实现comparable接口覆盖compareTo方法。这种方式也称为元素的自然顺序,也叫做默认顺序。

    这时,我们就考虑一个问题,当元素真的不具备比较性的时候,应该怎么办?

    也就是不能实现comparable接口和其中的compareTo();

    还有,你实现的比较方式和现在的需求不符合了,去强制改变类中的方法也是不现实的。

    这就有了TreeSet的第二种排序方式。

    这时就需要让集合自身具备比较性。

    让容器去决定元素哪个大或小,也就是两个人去找集合,让集合去比较二个人,而不是两个人相互的去比较。

    也就是在集合一初始化的时候,就有了比较的方式。

    TreeSet(Comparator<? superE> comparator)
    构造一个新的空 TreeSet,它根据指定比较器进行排序。

    就用到了这个构造函数。

    比方说,需求是按照姓名排序,而上边是按照年龄优先排序

    classMyCompimplementsComparator

    {

        publicintcompare(Object o1,Object o2)

        {

           Student s1 = (Student)o1;

           Student s2 = (Student)o2;

           returns1.getName().compareTo(s2.getName());

          

        }

    }

    就使用上边的方式去创建一个本身具备比较的集合。

    当集合自身具备比较性质和对象也具有比较性质的时候,优先使用集合自身的比较方法。也就是以比较器为主。

    比较器比较常用一些。

    以return 0 来确定元素是否存在。


  • 相关阅读:
    虚拟机docker开启服务,本地无法进行访问
    make编译提示:make cc Command not found 解决办法
    yum -y install git 无法安装...提示There are no enabled repos.
    linux 安装mysql
    linux 配置环境变量
    HTML5第三天 无序有序列表、相对绝对路径
    JavaScript第一天
    HTML第二天
    mysql流程控制语句
    mysql存储过程和函数
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3007031.html
Copyright © 2020-2023  润新知