第11条:考虑实现Comparable接口
1、Java平台库库的所有值类(value classes)都实现了 Comparable接口。比较某对象与另指定对象的顺序。当这个物件小于、等于、大于 指定对象时,分别传回负整数、0、正整数。如果指定对象的型别不允许与这个对象进行比较,就抛出ClassCastException异常。
2、运用 compareTo()所做的相等性测试必须遵守equals()所遵守的切约束:反身性、对称性、递移性和有效性。所以 equals() 的告诫同样适用于此:对于个可实体化(instantiable)class,并不存在个「既 可增加新外观(aspect)以扩展 class、又能维持 compareTo()契约」的办法(条 款 7)。equals()的迂回解法在此也同样适用:如果你打算对个实现了 Comparable 的 class 增加个有意义的外观(aspect),请不要扩展(继承)这个 class,而是另写个 class,其有个字段包含这个 class(译注:亦即不使用继承, 改用复合),然后提供个返回该字段的 "view"(映像)函式。这种方法使你得 以自由实现第个 class 的 compareTo(),同时允许其客户必要时将第个 class 的实体视为第个class的实体。
如果compareTo的相等性测试与equals的相等性测试不一致的时候可能出现问题,
例如:BigDecimal类,它的compareTo()与equals()不一致。如果 你创建个 HashSet,然后为它添加新元素 new BigDecimal(-0.0f)和 new BigDecimal(0.0f),这个 set 将含有 2 个元素,这是因为以 equals()比较述两个 BigDecimal 元素,结果并不相等(译注:因此得以都被放入「元素不得重复」的 set )。如果改用 TreeSet 而不是 HashSet,进行同样过程,将只含有1个元素,因为透过compareTo()比较两个BigDecimal,结果相等
1、Java平台库库的所有值类(value classes)都实现了 Comparable接口。比较某对象与另指定对象的顺序。当这个物件小于、等于、大于 指定对象时,分别传回负整数、0、正整数。如果指定对象的型别不允许与这个对象进行比较,就抛出ClassCastException异常。
2、运用 compareTo()所做的相等性测试必须遵守equals()所遵守的切约束:反身性、对称性、递移性和有效性。所以 equals() 的告诫同样适用于此:对于个可实体化(instantiable)class,并不存在个「既 可增加新外观(aspect)以扩展 class、又能维持 compareTo()契约」的办法(条 款 7)。equals()的迂回解法在此也同样适用:如果你打算对个实现了 Comparable 的 class 增加个有意义的外观(aspect),请不要扩展(继承)这个 class,而是另写个 class,其有个字段包含这个 class(译注:亦即不使用继承, 改用复合),然后提供个返回该字段的 "view"(映像)函式。这种方法使你得 以自由实现第个 class 的 compareTo(),同时允许其客户必要时将第个 class 的实体视为第个class的实体。
如果compareTo的相等性测试与equals的相等性测试不一致的时候可能出现问题,
例如:BigDecimal类,它的compareTo()与equals()不一致。如果 你创建个 HashSet,然后为它添加新元素 new BigDecimal(-0.0f)和 new BigDecimal(0.0f),这个 set 将含有 2 个元素,这是因为以 equals()比较述两个 BigDecimal 元素,结果并不相等(译注:因此得以都被放入「元素不得重复」的 set )。如果改用 TreeSet 而不是 HashSet,进行同样过程,将只含有1个元素,因为透过compareTo()比较两个BigDecimal,结果相等
测试例子:
import java.util.ArrayList;
import java.util.List;
public class TestCompare {
static class Person implements java.lang.Comparable<Person> {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int compareTo(Person person) {
String _name = person.getName();
int _age = person.getAge();
if (_age == age) {
return name.compareTo(_name);
}
return _age - age;
}
@Override
public String toString() {
return "name=" + name + "\tage=" + age;
}
}
public static void main(String[] args) {
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("zhangs", 21));
persons.add(new Person("zhangs", 24));
persons.add(new Person("lisi", 21));
persons.add(new Person("wanwu", 21));
persons.add(new Person("zhangs1", 21));
java.util.Collections.sort(persons);
for (Person person : persons) {
System.out.println(person);
}
}
}