Comparable接口
阅读原文时间:2021年04月20日阅读:3

官方文档api

java.lang 

接口 Comparable

类型参数:

T - 可以与此对象进行比较的那些对象的类型

所有已知子接口:

DelayedNameRunnableScheduledFutureScheduledFuture

所有已知实现类:

Authenticator.RequestorTypeBigDecimalBigIntegerBooleanByteByteBufferCalendarCharacterCharBuffer, CharsetClientInfoStatusCollationKeyComponent.BaselineResizeBehaviorCompositeNameCompoundNameDateDate, Desktop.ActionDiagnostic.KindDialog.ModalExclusionTypeDialog.ModalityTypeDoubleDoubleBufferDropMode, ElementKindElementTypeEnumFileFloatFloatBufferFormatter.BigDecimalLayoutFormFormSubmitEvent.MethodType, GregorianCalendarGroupLayout.AlignmentIntBufferIntegerJavaFileObject.KindJTable.PrintModeKeyRep.Type, LayoutStyle.ComponentPlacementLdapNameLongLongBufferMappedByteBufferMemoryTypeMessageContext.Scope, ModifierMultipleGradientPaint.ColorSpaceTypeMultipleGradientPaint.CycleMethodNestingKindNormalizer.Form, ObjectNameObjectStreamFieldProxy.TypeRdnResource.AuthenticationTypeRetentionPolicyRoundingMode, RowFilter.ComparisonTypeRowIdLifetimeRowSorterEvent.TypeService.ModeShortShortBuffer, SOAPBinding.ParameterStyleSOAPBinding.StyleSOAPBinding.UseSortOrderSourceVersion, SSLEngineResult.HandshakeStatusSSLEngineResult.StatusStandardLocationStringSwingWorker.StateValue, Thread.StateTimeTimestampTimeUnitTrayIcon.MessageTypeTypeKindURIUUIDWebParam.ModeXmlAccessOrder, XmlAccessTypeXmlNsForm


public interface Comparable

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

实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射(TreeMap)中的键或有序集合(如TreeSet)中的元素,无需指定比较器

对于类 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 的成员。

从以下版本开始:

1.2

另请参见:

Comparator


方法摘要

int

**[compareTo](http://dlc.sun.com.edgesuite.net/jdk/jdk-api-localizations/jdk-api-zh-cn/builds/latest/html/zh_CN/api/java/lang/Comparable.html#compareTo%28T%29)**([T](http://dlc.sun.com.edgesuite.net/jdk/jdk-api-localizations/jdk-api-zh-cn/builds/latest/html/zh_CN/api/java/lang/Comparable.html "Comparable 中的类型参数")&nbsp;o) 
          比较此对象与指定对象的顺序。

方法详细信息

compareTo

int compareTo(T o)

比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

实现类必须确保对于所有的 x 和 y 都存在 sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) 的关系。(这意味着如果 y.compareTo(x) 抛出一个异常,则 x.compareTo(y) 也要抛出一个异常。)

实现类还必须确保关系是可传递的:(x.compareTo(y)>0 && y.compareTo(z)>0) 意味着 x.compareTo(z)>0。

最后,实现者必须确保 x.compareTo(y)==0 意味着对于所有的 z,都存在 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。 强烈推荐(x.compareTo(y)==0) == (x.equals(y)) 这种做法,但并不是 严格要求这样做。一般来说,任何实现 Comparable 接口和违背此条件的类都应该清楚地指出这一事实。推荐如此阐述:“注意:此类具有与 equals 不一致的自然排序。”

在前面的描述中,符号 sgn(expression) 指定 signum 数学函数,该函数根据 expression 的值是负数、零还是正数,分别返回 -1、0或 1 中的一个值。

参数:

o - 要比较的对象。

返回:

负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。

抛出:

[ClassCastException](http://dlc.sun.com.edgesuite.net/jdk/jdk-api-localizations/jdk-api-zh-cn/builds/latest/html/zh_CN/api/java/lang/ClassCastException.html "java.lang 中的类") - 如果指定对象的类型不允许它与此对象进行比较。

java compare 接口

Java 算法 设计模式 框架 

1. 两种比较接口分析

在  “ 集合框架 ” 中有两种比较接口: Comparable 接口和 Comparator 接口。 Comparable 是通用的接口,用户可以实现它来完成自己特定的比较,而 Comparator 可以看成一种算法的实现,在需要容器集合实现比较功能的时候,来指定这个比较器,这可以看成一种设计模式,将算法和数据分离。

前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用。

一个类实现了 Camparable 接口表明这个类的对象之间是可以相互比较的。如果用数学语言描述的话就是这个类的对象组成的集合中存在一个全序。这样, 这个类对象组成的集合就可以使用 Sort 方法排序了。

而 Comparator 的作用有两个:

1 、如果类的设计师没有考虑到 Compare 的问题而没有实现 Comparable 接口,可以通过 Comparator 来实现比较算法进行排序;

2 、为了使用不同的排序标准做准备,比如:升序、降序或其他什么序。

2 Comparable 接口

public interface Comparable {

     public int compareTo(T o);

}

java.lang. Comparable 接口定义类的自然顺序,实现该接口的类就可以按这种方式排序。  

1 ) int compareTo(Object o): 比较当前实例对象与对象 o ,如果位于对象 o 之前,返回负值,如果两个对象在排序中位置相同,则返回 0 ,如果位于对象 o 后面,则返回正值。

2 )在 Java 2 SDK 版本 1.4 中有二十四个类实现 Comparable 接口。下表展示了 8 种基本类型的自然排序。虽然一些类共享同一种自然排序,但只有相互可比的类才能排序。

排序

BigDecimal,BigInteger,Byte,Double, Float,Integer,Long,Short

按数字大小排序

Character

按 Unicode 值的数字大小排序

String

按字符串中字符 Unicode 值排序

利用 Comparable 接口创建自己的类的排序顺序,只是实现 compareTo() 方法的问题。通常就是依赖几个数据成员的自然排序。同时类也应该覆盖 equals() 和 hashCode() 以确保两个相等的对象返回同一个哈希码。

这个接口的作用: 如果数组或者集合中的(类)元素实现了该接口的话 ,  我们就可以调用 Collections.sort 和Arrays.sort 排序,或应用于有序集合 TreeSet 和 TreeMap 中。

下面设计一个有序的类 Person ,它实现 Comparable 接口,以年龄为第一关键字,姓名为第二关键字升序排序。

Person.java

package com.zj.sort.comparable;

public class Person  implements Comparable {

     private int  age ;

     private String  name ;

     public Person(  int age, String name) {

        this .  age = age;

        this .  name = name;

    }

     public int compareTo(Person person) {

        int cop =  age - person.getAge();

        if (cop != 0)

            return cop;

        else

            return  name .compareTo(person.  name );

    }

     public int getAge() {

        return  age ;

    }

     public String getName() {

        return  name ;

    }

     public int hashCode() {

        int result = 17;

       result = 37 * result +  age ;

       result = 37 * result +  name .hashCode();

        return result;

    }

     public boolean equals(Object o) {

        if (!(o  instanceof Person))

            return false ;

       Person person = (Person) o;

        return (  age == person.  age ) && (  name .equals(person.  name ));

    }

     public String toString() {

        return (  age +  "{" +  name +  "}" );

    }

}

2.1 测试 Arrays.sort ()方法

ArraysSortUnit.java

package com.zj.sort.comparable;

import java.util.Arrays;

import com.zj.compare.Person;

public class ArraysSortUnit {

     public static void main(String[] args) {

       Person[] ps = {  new Person(20,  "Tom" ),  new Person(20,  "Jeff" ),

               new Person(30,  "Mary" ),  new Person(20,  "Ada" ),

               new Person(40,  "Walton" ),  new Person(61,  "Peter" ),

               new Person(20,  "Bush" ) };

       System.  out .println(Arrays. toString (ps));

       Arrays. sort (ps);

       System.  out .println(Arrays. toString (ps));

    }

}

结果:

[20{Tom}, 20{Jeff}, 30{Mary}, 20{Ada}, 40{Walton}, 61{Peter}, 20{Bush}]

[20{Ada}, 20{Bush}, 20{Jeff}, 20{Tom}, 30{Mary}, 40{Walton}, 61{Peter}]

2.2 测试 Collections.sort ()方法

CollctionsSortUnit.java

package com.zj.sort.comparable;

import java.util.Arrays;

import java.util.Collections;

import com.zj.compare.Person;

public class CollctionsSortUnit {

     public static void main(String[] args) {

       Person[] ps = {  new Person(20,  "Tom" ),  new Person(20,  "Jeff" ),

               new Person(30,  "Mary" ),  new Person(20,  "Ada" ),

                new Person(40,  "Walton" ),  new Person(61,  "Peter" ),

               new Person(20,  "Bush" ) };

       System.  out .println(Arrays. toString (ps));

       Collections. sort (Arrays. asList (ps));

       System.  out .println(Arrays. toString (ps));

    }

}

结果:

[20{Tom}, 20{Jeff}, 30{Mary}, 20{Ada}, 40{Walton}, 61{Peter}, 20{Bush}]

[20{Ada}, 20{Bush}, 20{Jeff}, 20{Tom}, 30{Mary}, 40{Walton}, 61{Peter}]

2.3 测试 TreeSet

TreeSetUnit.java

package com.zj.sort.comparable;

import java.util.TreeSet;

import com.zj.compare.Person;

public class TreeSetUnit {

     public static void main(String[] args) {

       TreeSet set =  new TreeSet();

       set.add(  new Person(20,  "Tom" ));

       set.add(  new Person(20,  "Jeff" ));

       set.add(  new Person(30,  "Mary" ));

       set.add(  new Person(20,  "Ada" ));

       set.add(  new Person(40,  "Walton" ));

       set.add(  new Person(61,  "Peter" ));

       set.add(  new Person(20,  "Bush" ));

       System.  out .println(set);

    }

}

结果:

[20{Ada}, 20{Bush}, 20{Jeff}, 20{Tom}, 30{Mary}, 40{Walton}, 61{Peter}]

2.4 测试 TreeMap

TreeMapUnit.java

package com.zj.sort.comparable;

import java.util.TreeMap;

import com.zj.compare.Person;

public class TreeMapUnit {

     public static void main(String[] args) {

       TreeMap map =  new TreeMap();

       map.put(  new Person(20,  "Tom" ),  "Tom" );

       map.put(  new Person(20,  "Jeff" ),  "Jeff" );

       map.put(  new Person(30,  "Mary" ),  "Mary" );

       map.put(  new Person(20,  "Ada" ),  "Ada" );

       map.put(  new Person(40,  "Walton" ),  "Walton" );

       map.put(  new Person(61,  "Peter" ),  "Peter" );

       map.put(  new Person(20,  "Bush" ),  "Bush" );

       System.  out .println(map);

    }

}

结果:

{20{Ada}=Ada, 20{Bush}=Bush, 20{Jeff}=Jeff, 20{Tom}=Tom, 30{Mary}=Mary, 40{Walton}=Walton, 61{Peter}=Peter}

3. Comparator 接口

public interface Comparator {

     int compare(T o1, T o2);

     boolean