1.Comparable接口,用来做什么。
2.判定类实现的Comparable接口是否正确的方法。
3.不要扩展一个已经实现了Comparable接口的类来增加用于比较的值组件。
 
 
1.Comparable接口,用来做什么?
---Comparable接口-----
public interface Comparable<T> { int compareTo(T t); }
---Comparable接口-----
Comparable接口用来做什么?实现了Comparable接口的类,具备什么功能?
“This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method
 
Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort (and Arrays.sort). Objects that implement this interface can be used as keys in a sorted map or as elements in a sorted set, without the need to specify a comparator.
实现了Comparable接口的类,它的实例就具备了排序功能。然后,把实现了Comparable接口的类的实例,添加到List或者array集合中,调用Collections.sort或者Arrays.sort就可以得到一个排好序的集合。
 
 
一个类实现Comparable接口时,要遵守如下约定:
 
1.将当前对象与指定对象进行比较。当该对象小于、等于、或大于指定对象的时候,分别返回一个负整数、零或者正整数。如果由于指定对象的类型而无法与该对象进行比较,则抛出ClassCastException异常。
 
------这是在实现时,首要考虑的约定。按照该约定来实现Comparable接口。
 
例子:
选定要比较的是类中的哪个属性,下面比较的是Sal属性。
public class Employee implements Comparable<Employee> {

  private int EmpID ;
private String Ename;
private double Sal ;
private static int i; public Employee() {
EmpID = i++;
Ename = "dont know";
Sal = 0.0;
} public Employee(String ename, double sal) {
EmpID = i++;
Ename = ename;
Sal = sal;
} public String toString() {
return "EmpID " + EmpID + "\n" + "Ename " + Ename + "\n" + "Sal " + Sal ;
} public int compareTo(Employee arg0) {
// TODO Auto-generated method stub
if (Sal < arg0. Sal)
return -1;
else if (Sal == arg0.Sal)
return 0;
else
return 1; }
}

然后就可以使用该类了,结合List<T>,Array集合实现对集合中的元素进行排序,如下:

public class ComparableDemo {

  public static void main(String[] args) {

    List<Employee> ts1 = new ArrayList<Employee>();
ts1.add(new Employee( "Tom", 40000.00));
ts1.add(new Employee( "Harry", 20000.00));
ts1.add(new Employee( "Maggie", 50000.00));
ts1.add(new Employee( "Chris", 70000.00));
Collections.sort(ts1);
Iterator<Employee> itr = ts1.iterator(); System.out.println( "------List--------");
while (itr.hasNext()) {
Object element = itr.next();
System. out.println(element + "\n" ); } System.out.println( "-----Array--------");
Employee[] oneArray =
{ new Employee("Peter" , 30000.00), new Employee( "Harry", 20000.00),
new Employee("Maggie" , 50000.00)};
Arrays.sort(oneArray);
for (Employee one : oneArray) {
System. out.println(one + "\n" );
} }
}
输出结果:是一个升序排序,从小到大。
------List--------
EmpID 1
Ename Harry
Sal 20000.0
 
EmpID 0
Ename Tom
Sal 40000.0
 
EmpID 2
Ename Maggie
Sal 50000.0
 
EmpID 3
Ename Chris
Sal 70000.0
 
-----Array--------
EmpID 5
Ename Harry
Sal 20000.0
 
EmpID 4
Ename Peter
Sal 30000.0
 
EmpID 6
Ename Maggie
Sal 50000.0
 
2.判定类实现的Comparable接口是否正确的方法
 
根据《effective Java>,在判定类实现的Comparable接口实现是否正确时,使用下列通用约定来判定:
 
1)实现者必须确保所有的x和y都满足sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。(这也暗示着,当且仅当y.compareTo(x)抛出异常时,x.compareTo(y)才必须抛出异常。
使用上述的例子,可以这样写个单元测试:
  Employee one = new Employee( "Tom", 40000.00);
Employee two = new Employee("Chris", 70000.00);
if (one.compareTo( two) == -two .compareTo(one)) {
System. out.println("satisfy rule one." );
}
2)实现者还必须确保这个关系时可传递的:(x.compareTo(y) > 0 && y.compareTo(z)>0),暗示着x.compareTo(z) > 0。---传递性。
使用上述的例子,可以这样写个单元测试:
  Employee x = new Employee( "Tom", 40000.00);
Employee y = new Employee( "ChrisY", 30000.00);
Employee z = new Employee( "Chris", 20000.00);
if (x.compareTo(y) > 0 && y.compareTo(z) > 0 && x.compareTo(z) > 0) { System. out.println("satisfy rule No.two" ); }
3)实现者必须确保x.compareTo(y) == 0暗示着所有的z都满足sgn(x.compareTo(z)) == sgn(y.compareTo(z))。
使用上述的例子,可以这样写个单元测试:
    Employee x = new Employee( "Tom", 40000.00);
Employee y = new Employee( "ChrisY", 40000.00);
Employee z = new Employee( "Chris", 20000.00);
if (x.compareTo(y) == 0) {
if (x.compareTo(z) == y.compareTo(z)) {
System. out.println("satisfy rule No.threee" );
}
}
总的来说,这三条通用约定,是用来指导你编写单元测试的。如果,你实现的Compareable接口违反了这三条约定,那么,将不能完好的与List,Array等集合协作。
 
3.不要扩展一个已经实现了Comparable接口的类来增加用于比较的值组件
 
如果你想为一个实现了Comparable接口的类增加值组件,请不要扩展这个类;而是要编写一个不相关的类,其中包含第一个类的一个实例。然后提供一个“视图(view)"方法返回这个实例。这样既可以让你自由地在第二个类上实现compareTo方法,同时也允许它的客户端在必要的时候,把第二个类的实例视同第一个类的实例。
 
 
例子:假设,在比较职员的时候,还考虑到这个职员当前的级别。当两个职员的级别相等时,才比较他们的销售额;否则,则比较职员的级别,职员级别高的,排在后面,按照升序排列。
public class NewEmployee implements Comparable<NewEmployee> {

  public static final int Low = 10;
public static final int Middle = 20;
public static final int High = 30; private int EmpID ;
private String Ename;
private double Sal ;
private static int i; private Grade oneGrade; public NewEmployee() {
EmpID = i++;
Ename = "dont know";
Sal = 0.0; oneGrade = new Grade( Low );
} public NewEmployee(String ename, double sal, Grade grade) {
EmpID = i++;
Ename = ename;
Sal = sal;
oneGrade = grade;
} public String toString() {
return "EmpID " + EmpID + "\n" + "Ename " + Ename + "\n" + "Sal " + Sal + "\n" + "Grade "
+ getGradeName( oneGrade.getGrade());
} private String getGradeName( int grade) {
switch (grade) {
case Low :
return "Low" ;
case Middle :
return "Middle" ;
case High :
return "High" ; default:
return "Null" ; }
} public int compareTo(NewEmployee arg0) {
// TODO Auto-generated method stub if ( oneGrade.compareTo(arg0. oneGrade) == 0) {
if ( Sal < arg0. Sal) {
return -1;
} else if (Sal == arg0. Sal) {
return 0;
} else {
return 1;
} } else {
return oneGrade.compareTo(arg0. oneGrade);
} } } --------
public class NewComparableDemo { public static void main(String[] args) { List<NewEmployee> ts1 = new ArrayList<NewEmployee>();
ts1.add( new NewEmployee( "Tom" , 40000.00, new Grade(NewEmployee. Middle)));
ts1.add( new NewEmployee( "Harry" , 20000.00, new Grade(NewEmployee. Low)));
ts1.add( new NewEmployee( "Maggie" , 50000.00, new Grade(NewEmployee. High)));
ts1.add( new NewEmployee( "Chris" , 70000.00, new Grade(NewEmployee. Low)));
Collections. sort(ts1);
Iterator<NewEmployee> itr = ts1.iterator(); while (itr.hasNext()) {
Object element = itr.next();
System. out .println(element + "\n" ); } NewEmployee x = new NewEmployee( "Tom" , 40000.00, new Grade(NewEmployee.Middle ));
NewEmployee y = new NewEmployee( "Harry" , 20000.00, new Grade(NewEmployee.Low ));
if (x.compareTo(y) == -y.compareTo(x)) {
System. out .println("satisfy rule No.one" );
} NewEmployee x1 = new NewEmployee( "Tom" , 40000.00, new Grade(NewEmployee.Middle ));
NewEmployee y1 = new NewEmployee( "Harry1" , 70000.00, new Grade(NewEmployee.Low ));
NewEmployee z1 = new NewEmployee( "Harry2" , 30000.00, new Grade(NewEmployee.Low ));
if (x1.compareTo(y1) > 0 && y1.compareTo(z1) > 0 && x1.compareTo(z1) > 0) {
System. out .println("satisfy rule No.two" );
} NewEmployee x2 = new NewEmployee( "Tom2" , 70000.00, new Grade(NewEmployee.Middle ));
NewEmployee y2 = new NewEmployee( "Harry2" , 70000.00, new Grade(NewEmployee.Middle ));
NewEmployee z2 = new NewEmployee( "Harry2" , 30000.00, new Grade(NewEmployee.Low ));
if (x2.compareTo(y2) == 0) {
if (x2.compareTo(z2) == y2.compareTo(z2)) {
System. out .println("satisfy rule No.three" );
}
} }
}

 

输出结果:
EmpID 1
Ename Harry
Sal 20000.0
Grade Low
 
EmpID 3
Ename Chris
Sal 70000.0
Grade Low
 
EmpID 0
Ename Tom
Sal 40000.0
Grade Middle
 
EmpID 2
Ename Maggie
Sal 50000.0
Grade High
 
satisfy rule No.one
satisfy rule No.two
satisfy rule No.three

Item 12 考虑实现Comparable接口的更多相关文章

  1. 12.Java中Comparable接口,Readable接口和Iterable接口

    1.Comparable接口 说明:可比较(可排序的) 例子:按照MyClass的y属性进行生序排序 class MyClass implements Comparable<MyClass> ...

  2. 第12条:考虑实现Comparable接口

    CompareTo方法没有在Object中声明,它是Comparable接口中的唯一的方法,不但允许进行简单的等同性比较,而且允许执行顺序比较.类实现了Comparable接口,就表明它的实例具有内在 ...

  3. EffectiveJava(12)考虑实现Comparable接口

    考虑实现Comparable接口 compareTo方法 Comparable接口的唯一方法,允许进行简单的等同性比较,允许执行顺序比较 Comparable接口被所有值类实现.所以如果一个值类有非常 ...

  4. Java6.0中Comparable接口与Comparator接口详解

    Java6.0中Comparable接口与Comparator接口详解 说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者 ...

  5. 十三、实现Comparable接口和new Comparator<T>(){ }排序的实现过程

    参考:https://www.cnblogs.com/igoodful/p/9517784.html Collections有两种比较规则方式,第一种是使用自身的比较规则: 该类必须实现Compara ...

  6. java实现Comparable接口和Comparator接口,并重写compareTo方法和compare方法

    原文地址https://segmentfault.com/a/1190000005738975 实体类:java.lang.Comparable(接口) + comareTo(重写方法),业务排序类 ...

  7. Java之comparable接口

    comparable 接口: 1. 问题:java.util.Collections 类中的方法 Collections.sort(List list) 是根据什么确定容器中对象的“大小”顺序的? 2 ...

  8. Java的Comparable接口的一个陷阱

    转载自:http://my.oschina.net/jack230230/blog/56339 Java的Comparable接口提供一个对实现了这个接口的对象列表进行排序的办法.原始的排序对于简单的 ...

  9. 关于comparable接口

    参考博客: https://blog.csdn.net/nvd11/article/details/27393445 第一个例子 @Test public void fun1(){ List list ...

随机推荐

  1. M2迭代分数分配

    M2中仍然依据每个成员的工作量,贡献度分配相应得分. 成员 得分 申开亮 25 王皓南 24 许晋 21 黄玉冰 20 王宇杰 18 吴润凡 17 巴丹益昔 15

  2. 20172314 Android程序设计 实验四

    课程:<程序设计与数据结构> 班级: 1723 姓名: 方艺雯 学号:20172314 实验教师:王志强 实验日期:2018年5月30日 必修/选修: 必修 1.实验内容及要求 (1)An ...

  3. 《梦断代码Dreaming In Code》阅读笔记(三)

    最后这几章感觉上更多是从软件完成整体上来讲的.比如说技术.方法等. 在我看来,其实一个团队一直坚持一种好的.先进的方法是不可少的.如果一个优秀的团队刚愎自用,只随着成员们喜好发展,那不能长久.比如说, ...

  4. MyEclipse2013使用总结

    1.myeclipse10中怎样将建的包设置成树形结构或者并列结构. 右上边三角那里进去设置选第一个是显示完整的包名,第二个显示的是树形结构这种方法没效 2.从高版本到项目的低版本的MyEclipse ...

  5. Java 变量和输入输出

    一些重要知识 一个源文件里只能有一个public类,其它类数量不限.文件名与public类名相同 JAVA程序严格区分大小写 JAVA应用程序的执行入口是main方法固定写法:public stati ...

  6. 算法与数据结构3.1 stack

    ★实验任务 一天,小 L 发现了一台支持一下操作的机器: IN x:将整数 x 入栈 POP:将栈顶元素出栈 ASUB:出栈两个数,将两数差的绝对值入栈 COPY:将栈顶元素(如果有的话)复制一份,入 ...

  7. Python ZKPython 安装

    1.由于python客户端依赖c的客户端所以要先安装c版本的客户端cd zookeeper-3.4.5/src/c./configuremake make install 2.下载python扩展包, ...

  8. 【Linux】- CentOS安装Mysql 5.7

    CentOS7默认数据库是mariadb,而不是mysql.CentOS7的yum源中默认是没有mysql的.所以不能使用yum install直接安装. 下载mysql的repo源 cd /usr/ ...

  9. tomcat web页面管理应用配置

    大部分时候,我们的tomcat服务器都不是部署在本机,那么怎么样不通过ftp/sftp方式来将war包部署到tomcat容器呢? tomcat有提供web页面管理应用的功能. 我们来看看怎么配置实现该 ...

  10. sublime Remote_encoding cp1252

    "remote_encoding": "cp1252",才能连接远程ftp