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. mysql唯一查询

    MySQL单一字段唯一其他字段差异性忽略查询.在使用MySQL时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返 ...

  2. UVALive - 6869 Repeated Substrings 后缀数组

    题目链接: http://acm.hust.edu.cn/vjudge/problem/113725 Repeated Substrings Time Limit: 3000MS 样例 sample ...

  3. Java常用类之File类

    File 类: 1. java.io.File 类代表系统文件名(路径名.文件名); 2. File 类常见的构造方法: 2.1. File(String pathname):通过将给定路径名字符串转 ...

  4. java — 排序算法

    1.冒泡排序 比较相邻元素,如果第一个比第二个大,就交换位置,每一次交换,当前 package BubbleSort; public class Test { public static void m ...

  5. 《剑指offer》---丑数

    本文算法使用python3实现 1. 问题1 1.1 题目描述:   把只包含因子2.3和5的数称作丑数(Ugly Number).判断一个数是否是丑数.   时间限制:1s:空间限制:32768K ...

  6. Ligerui首页的快速搭建

    一.目录 1.多层架构+MVC+EF+AUTOFAC+AUTOMAPPER: 2.MVC中验证码的实现(经常用,记录备用) 3.Ligerui首页的快速搭建 4.Ligerui Grid组件--学生信 ...

  7. MVC中验证码的实现(经常用,记录备用)

    一.目录 1.多层架构+MVC+EF+AUTOFAC+AUTOMAPPER: 2.MVC中验证码的实现(经常用,记录备用) 3.Ligerui首页的快速搭建 二 正文 Ok,我们的验证码开始,这篇文章 ...

  8. 第五部分shell项目一监控脚本

    需求: 使用shell定制各种个性化告警工具,但需要统一化管理.规范化管理. 思路:指定一个脚本包,包含主程序.子程序.配置文件.邮件引擎.输出日志等.主程序:作为整个脚本的入口,是整个系统的命脉.配 ...

  9. [C/C++] 结构体存储问题

    64位操作系统,不同类型变量对应的字节数为: char : 1个字节 char*(即指针变量) : 8个字节 //32位占4个字节 short int : 2个字节 int : 4个字节 unsign ...

  10. overflow:scroll 在ios 滚动卡顿

    使用 -webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果. 值 auto 使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止. touch 使用具有回 ...