zoukankan      html  css  js  c++  java
  • Java SortedSet为什么可以实现自动排序?

    Set中的SortedSet(SortedSet为TreeSet的实现接口),它们之间的继承关系如下:

    java.util.Set;

    java.util.SortedSet; 

    java.util.TreeSet; 

    SortedSet中的元素无序不可重复,但是存进去的元素可以按照元素大小顺序自动排序。结合以下代码来看:

    import java.util.*;
    import java.text.*;
    public class SortedSetTest01{
     public static void main(String[] args)throws Exception{
       SortedSet ss=new TreeSet();
       //数字类
       ss.add(12);
       ss.add(23);
       ss.add(45);
       ss.add(39);
       ss.add(45);
       Iterator it=ss.iterator();
       while(it.hasNext()){
         System.out.println(it.next());
       }
       //String类
       SortedSet str=new TreeSet();
       str.add("JACK");
       str.add("TOM");
       str.add("KING");
       str.add("SUN");
       it=str.iterator();
       while(it.hasNext()){
         System.out.println(it.next());
       }
       //日期类
       String st1="2003-08-12";
       String st2="2004-09-17";
       String st3="2003-04-12";
       String st4="2013-09-04";
       
       SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
       Date t1=sdf.parse(st1);
       Date t2=sdf.parse(st2);
       Date t3=sdf.parse(st3);
       Date t4=sdf.parse(st4);
       
       SortedSet times=new TreeSet();
       times.add(t1);
       times.add(t2);
       times.add(t3);
       times.add(t4);
       
       it=times.iterator();
       while(it.hasNext()){
         Object element=it.next();
         if(element instanceof Date){
           Date d=(Date)element;
           System.out.println(sdf.format(d));
         }
       }
     }
    }

    编译运行后输出:

    12
    23
    39
    45
    JACK
    KING
    SUN
    TOM
    2003-04-12
    2003-08-12
    2004-09-17
    2013-09-04

    以上代码展示了存在SortedSet中的元素可以按照元素大小进行排序,这些元素可以是数字类,字符串类或日期类等。既然知道了SortedSet的这一特性,那么SortedSet集合存储元素为什么可以自动排序?

    在上面的代码中我们实现了SortedSet中的数字,字符串和日期类的自动排序,那么如果我们自定义几个User类型对象,然后把它们添加到SortedSet集合中去,可以实现像上面那样的自动排序吗?试一下。

    import java.util.*;
    public class SortedSetTest02{
     public static void main(String[] args){
       SortedSet users=new TreeSet();
       User u1=new User(12);
       User u2=new User(16);
       User u3=new User(23);
       User u4=new User(32);
       User u5=new User(43);
       
       users.add(u1);
       users.add(u2);
       users.add(u3);
       users.add(u4);
       users.add(u5);
       Iterator it=users.iterator();
       while(it.hasNext()){
         System.out.println(it.next());
       }
     }
    }
    class User{
     int age;
     User(int age){
       this.age=age;
     }
     public String toString(){
       return "User[age="+age+"]";
     }
    }

    编译通过,运行后出错,输出:

    Exception in thread "main" java.lang.ClassCastException: User cannot be cast to java.lang.Comparable

    at java.util.TreeMap.compare(Unknown Source)

    at java.util.TreeMap.put(Unknown Source)

    at java.util.TreeSet.add(Unknown Source)

    at SortedSetTest02.main(SortedSetTest02.java:14)

    User cannot be cast to java.lang.Comparable,也就是说User不可以转变成可比较的类型。所以User必须实现Comparable接口(也就是第一个程序例子中数字,字符串,日期底层已经实现了Comparable接口),即class User implements Comparable{ }。我们知道一个类实现一个接口就实现了这个接口的所有方法,SortedSet集合中的元素之所以可以自动排序,是因为使用add()方法添加进去的元素实现了Comparable接口中的CompareTo()方法。

    上述代码中,如果我们给定一个需求,按照User的年龄排序,那么就需要编写一个比较规则,

    public int compareTo(Object o){
       //编写一个比较规则
       int age1=this.age;
       int age2=((User)o).age;
       return age1-age2;
     }

    compareTo的用法为u1.compareTo(u2),this为u1,括号里的参数o为u2,因为括号里的参数类型为Object类型,而Object类型没有age这个属性,所以必须把o强制类型转换为User类型,即(User)o。修改之后的整体代码如下:

    import java.util.*;
    public class SortedSetTest02{
     public static void main(String[] args){
       SortedSet users=new TreeSet();
       User u1=new User(12);
       User u2=new User(16);
       User u3=new User(23);
       User u4=new User(32);
       User u5=new User(43);
       
       users.add(u1);
       users.add(u2);
       users.add(u3);
       users.add(u4);
       users.add(u5);
       Iterator it=users.iterator();
       while(it.hasNext()){
         System.out.println(it.next());
       }
     }
    }
    class User implements Comparable{
     int age;
     User(int age){
       this.age=age;
     }
     public String toString(){
       return "User[age="+age+"]";
     }
     //实现java.lang.Comparable;接口中的compareTo方法
     //该方法程序员负责实现,SUN提供的程序已经调用了该方法
     //需求:按照User的年龄排序
     public int compareTo(Object o){  //u1.compareTo(u2)
       //编写一个比较规则
       int age1=this.age;   
       int age2=((User)o).age;
       return age1-age2;
     }
    }

    编译运行后输出:

    User[age=12]
    User[age=16]
    User[age=23]
    User[age=32]
    User[age=43]

    除此之外,还有另一种方法实现SortedSet集合排序:使用java.util.Comparator;来单独编写一个比较器,创建TreeSet集合的时候提供这个比较器,即SortedSet products=new TreeSet(new ProductComparator()); 代码如下:

    import java.util.*;
    public class SortedSetTest03{
     public static void main(String[] args){
       //创建TreeSet集合的时候提供一个比较器
       SortedSet products=new TreeSet(new ProductComparator());
       Product p1=new Product(3.4);
       Product p2=new Product(4.0);
       Product p3=new Product(3.6);
       Product p4=new Product(7.6);
       Product p5=new Product(3.7);
       
       products.add(p1);
       products.add(p2);
       products.add(p3);
       products.add(p4);
       products.add(p5);
       
       Iterator it=products.iterator();
       while(it.hasNext()){
         System.out.println(it.next());
         }
     }
    }
    class Product{
     double price;
     Product(double price){
       this.price=price;
     }
     public String toString(){
       return price + "";
     }
    }
    //单独编写一个比较器
    class ProductComparator implements Comparator{
     //需求:按照商品价格排序
     public int compare(Object o1,Object o2){
       double price1=((Product)o1).price;
       double price2=((Product)o2).price;
       if (price1==price2){
         return 0;
       }else if(price1>price2){
         return -1;
       }
       return 1;
     }
    }

    编译运行后输出:

    7.6
    4.0
    3.7
    3.6
    3.4

    wx搜索“程序员考拉”,专注java领域,一个伴你成长的公众号!


  • 相关阅读:
    zabbix linux 客户端编译安装
    yum安装grafana
    zabbix 安装和配置
    安装PHP
    wrk压力测试
    新加坡地图
    shell中去除变量去除所有空格或者去除变量首尾空格的常用几种方法
    新鲜出炉!春招-面试-阿里钉钉、头条广告,美团面经分享,看我如何拿下offer!
    面试阿里,字节跳动90%会被问到的Java异常面试题集,史上最全系列!
    最新出炉,字节跳动一二三面面经,看我如何一步一步攻克面试官?
  • 原文地址:https://www.cnblogs.com/naihuangbao/p/9444481.html
Copyright © 2011-2022 走看看