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. Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件

    作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 示例代码下载 : -- CSDN : htt ...

  2. Python 循环语句和运算符

    while 循环 while 条件 : //条件为True时,执行while下带有缩进的语句 语句1 语句2 语句3 for循环 for循环可以用来遍历某一对象(遍历:通俗点说,就是把这个循环中的第一 ...

  3. SOA架构的理解

    实践论认为:从实践提升到理论,再由理论指导实践,由此向前发展.目前SOA的发展的情况………… 通过不少实践,SOA的模型己经被公认为标准规范,目前是正需要进一步总结上升到理论的时候了. SOA架构的演 ...

  4. 再学习Webform页面生命周期

    参考文章: 在vs2010,新建一个aspx页面,页面头部有一行代码: <%@ Page Language="C#" AutoEventWireup="true&q ...

  5. hadoop下安装mysql

    http://www.cnblogs.com/zhuyp1015/p/3561470.html       第一步:先把这个文件放入到linux环境下桌面. 接着编写脚本:sudo apt-get u ...

  6. 【week2】 词频统计第一次更新

    词频统计: 对每个功能预计时间: 功能 预计(min) 实际(min) 数据流读入 20 40 正则规范字符串 15 20 排序 30 45 输出 20 30 其他   25 词频统计psp 日期 类 ...

  7. MVP开发模式的理解

    1.MVP是什么 如果从层次关系来讲,MVP属于Presentation层的设计模式.对于一个UI模块来说,它的所有功能被分割为三个部分,分别通过Model.View和Presenter来承载.Mod ...

  8. java 基础--switch--003

    1,break可以省略吗? default中的可以省略,其他的如果省略会执行下一个case,从下一个case的 break中中断.(case穿透) 2,default一定要在最后吗? 不是,可以在任意 ...

  9. IE BHO的IObjectWithSite接口

    Internet Explorer的BHO的对象必须实现IObjectWithSite接口.该接口是IE用来对插件进行管理和通讯的一个接口,其有SetSite和GetSite两个方法,当IE加载和卸载 ...

  10. vs code 自动补全效果不理想的问题

    之前一直用webstorm,最近换换口味,改用了VS Code,发现VS Code 智能提示得到的都不是我想要的 就比如  ! + tab ,HTML结构都出不来.经过一番搜索,发现是 VS Code ...