一、Comparable(内部排序接口)
实现该接口的类,支持自然排序(内排序)。Arrays.sort(Object[])和Collection.sort(Object[])要求对象必须实现Comparable接口
文档中指出:
- 如果该对象大于指定对象,返回正整数
- 如果该对象等于指定对象,返回0
- 如果该对象小于指定对象,返回负整数
- 建议(x.compareTo(y)==0) == x.equals(y)
- e.compareTo(null) 应该抛出NullPointerException
- 键a和b被添加到没有指定显示比较器的有序集合中。if(!a.equals(b) && a.compareTo(b))(eqauls方法与compareTo方法不一致)。在有序集合看来a和b是相等的,因此第2个键无法被添加到集合中。
针对第6点可以举个例子:
BigDecimal类的compareTo 与 equals 方法不一致。
public static void main(String[] args) {
Map<BigDecimal,String> map = new HashMap<BigDecimal,String>();
BigDecimal b1 = new BigDecimal(1.0);
BigDecimal b2 = new BigDecimal(1.00);
map.put(b1,"c1");
map.put(b2,"c2");
System.out.println(map.get(b1) + " " + map.get(b2)); // 输出 c1、c2
TreeSet<BigDecimal> set = new TreeSet<BigDecimal>();
set.add(b1);
set.add(b2);
for(BigDecimal b : set) {
System.out.println(b.floatValue()); // 只打印出1.0
}
}
HashMap通过 hashCode + equals 方法进行比较。 TreeSet 通过 compareTo进行比较。
在effctiveJava中 指出,Comparable接口,具有与equals方法一样的自反、传递、对称。所以同样与equals具有同样的特征:
没有一种简单的方法可以做到,在扩展一个新的可实例化的类时,既增加了新的特征,又保持了compareTo的约定(见我的文章)
对于如何编写compareTo方法,effectivejava中,同样给出了以下建议。并且推荐,自定义的类,可以考虑实现Comparable接口
- 实参为null,compareTo方法应抛出NullPointerException
- 参数不合适,应抛出ClassCastException
- 比较对象引用域,通过递归比较
- 如果对象有多个域,则从最重要的域开始比较
- compareTo没有指定返回值的大小,而只是指定返回值的符号,可利用这点进行优化
例子:
public int compareTo(Object obj) {
if(obj == null) {
throw new NullPointerException(); // 满足第1点
}
if(!(obj instanceof MyComparable)) {
throw new ClassCastException(); // 满足第2点
}
MyComparable o = (MyComparable) obj;
int x = o.p.compareTo(p);// p 是一个对象 ,满足第3、4点
if(x == 0) {
return o.y - y; // y 是个int型, 满足第5点,
//对于第5点请注意,确保 o.y -y 不会溢出!!!
}
return x;
}
二、Comparator(外部比较器)
可自己制定比较规则。在TreeSet中有应用,TresSet利用Comparator接口实现模板设计模式
文档中指出:
- 如果该对象大于指定对象,返回正整数
- 如果该对象等于指定对象,返回0
- 如果该对象小于指定对象,返回负整数
- 建议(x.compareTo(y)==0) == x.equals(y)
- 必须确保关系的传递性。即compare(x,y) > 0 且 compare(y,z) > 0,那么 compare(x,z) > 0
在本人看来,Comparable 与 Comparator 差别不大
疑问:那么Comparator具体的使用在什么地方呢?
JAVA API 的String 类 默认实现了Comparable接口,有默认的排序方式,但是如果我们想使用自己的排序方式呢?比如按照长度排序,那么就可以使用Comparator接口了。
class LengthComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。