现在的位置: 首页 > 综合 > 正文

JAVA中常用接口的介绍及使用示例:java.lang.Comparable

2018年05月23日 ⁄ 综合 ⁄ 共 3601字 ⁄ 字号 评论关闭

JAVA中常用接口的介绍及使用示例:java.lang.Comparable

JKD中说明

此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法

实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射(接口 java.util.SortedMap<K,V>)中的键或有序集合(接口 java.util.SortedSet<E>)中的元素,无需指定比较器(接口 java.util.Comparator<T>)

对于类 C 的每一个 e1 和 e2 来说,当且仅当 e1.compareTo(e2) == 0 与 e1.equals(e2) 具有相同的 boolean 值时,类 C 的自然排序才叫做与 equals 一致。注意,null 不是任何类的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也将抛出 NullPointerException。

建议(虽然不是必需的)最好使自然排序与 equals 一致。这是因为在使用自然排序与 equals 不一致的元素(或键)时,没有显式比较器的有序集合(和有序映射表)行为表现“怪异”。尤其是,这样的有序集合(或有序映射表)违背了根据 equals 方法定义的集合(或映射表)的常规协定。

例如,如果将两个键 a 和 b 添加到没有使用显式比较器的有序集合中,使 (!a.equals(b) && a.compareTo(b) == 0),那么第二个 add 操作将返回 false(有序集合的大小没有增加),因为从有序集合的角度来看,a 和 b 是相等的。

实际上,所有实现 Comparable 的 Java 核心类都具有与 equals 一致的自然排序。java.math.BigDecimal 是个例外,它的自然排序将值相等但精确度不同的 BigDecimal 对象(比如 4.0 和4.00)视为相等。

从数学上讲,定义给定类 C 上自然排序的关系式 如下:

      {(x, y)|x.compareTo(y) <= 0}。

整体排序的 是:

      {(x, y)|x.compareTo(y) == 0}。

它直接遵循 compareTo 的协定,商是 C 的等价关系,自然排序是 C 的整体排序。当说到类的自然排序与 equals 一致 时,是指自然排序的商是由类的 equals(Object) 方法定义的等价关系。

    {(x, y)|x.equals(y)}。

此接口是 Java Collections Framework 的成员。

笔者注:注意字符串与数字在一起的时候的排序,这个时候数字被当做字符处理,排序时需要指定比较器才可以比较准确。如将“loop1,loop5,loop11,loop2,loop13”进行排序,如果直接采用Collections.sort(或 Arrays.sort),得出的结果将会是:loop1,loop11,loop13,loop2,loop5。参见实例二部份中自定义比较器的实现,就可以得出正确的排序。

示例一:

public void comparableTest() {

       // TODO Auto-generated method stub

       String a="1",b="1";

       System.out.println(a.compareTo(b));

       Integer c=1,d=1;

       System.out.println(c.compareTo(d));

    }

 

示例二:

/**

     * 将传入的HashMap,将其中值为子HashMap的键进行排序,排好序后以List返回,List中存放的是排好序的、原HashMap的键。

     * 该排序通过Collections的sort方法,Collections是Collection的一个工具类,自定义排序,需要实现自定义的Comparator,默认的排序是按字符的ASCII进行排序的。

     * 其中需要注意的时,被排序的Map,必须具有相似的结构、相同的前缀,否则会报错,如List的键如下:

     * Map map = new HashMap();

     * map.put("loop7", "7");

     * map.put("loop3", "3");

     * map.put("loop1", "1");

     * map.put("loop15", "15");

     * ...

     * 他们都有相同的前缀loop,并且前缀中不能够包括数字,前缀可以是任意不包括数字的字符串.也就是说传入的HashMap,其子HashMap的键,一定要按上面的规则,否则将会报错.

     * @param map     包括待排序键的HashMap

     * @return        存放排好序后的HashMap的键的List

     */

    private static List hashMapKey2SortedList(Map map){

       List list = new ArrayList();

       Iterator iterator=map.keySet().iterator();

       while(iterator.hasNext()){

           String key=(String)iterator.next();

           Object obj=map.get(key);

           if(obj instanceof Map){

              list.add(key);

           }         

       }

       /**

        * 排序通过实现自定义比较器进行排序

        */

       Collections.sort(list,new Comparator(){

           public int compare(Object o1, Object o2) {

               String key1=o1.toString();

              String key2=o2.toString();

              String prefix="";

              for(int i=0;i<key1.length();i++){

                  String tmp=key1.substring(i,i+1);

                  try{

                     Integer.parseInt(tmp);

                  }catch(Exception e){

                     prefix+=tmp;

                  }

              }

              key1=key1.replace(prefix, "");

              key2=key2.replace(prefix, "");

              int key1_int=0;

              int key2_int=0;

              try{

                  key1_int=Integer.parseInt(key1);

              }catch(NumberFormatException e){

                 

              }

              try{

                  key2_int=Integer.parseInt(key2);

              }catch(NumberFormatException e){

                 

              }

             

              return key1_int-key2_int;

           }

       });

       return list;

    }

抱歉!评论已关闭.