0
点赞
收藏
分享

微信扫一扫

Effective Java -- 排序敏感的类建议实现Comparable接口

IT程序员 2022-04-03 阅读 62
java

原因

对于一个有排序需求的类,建议实现Comparable接口,因为这样可以让它轻松地被分类、搜索以及用在基于比较的集合中。

陈述

首先了解一下Comparable:它是一个带泛型的接口,且只有一个方法compareTo;

public interface Comparable<T> {
	public int compareTo(T o);
}

当你实现了这个接口,重写了compareTo方法,这个类便可以很方便地利用Java自带的方法进行排序操作,如Arrays.sort方法。

Java中的所有值类枚举类都实现了这个接口,值类实现Comparable接口的原因很简单,毕竟整天都在忙着比大小,作排序。枚举类的这个实现相对冷门,我们来一起看一下:
打开java.lang.Enum,找到compareTo方法
Enum类的comareTo方法
这里我们可以看到,首先是把两个枚举的class进行了对比(这里不深究其对比逻辑),然后直接输出了ordinal之差。

看一下ordinal是什么:
ordinal
说白了就是一个序号,这个序号怎么产生的呢,很简单,就是枚举在定义的时候顺序

举个例子:

public enum Type {
    A, // ordinal = 0
    B, // ordinal = 1
    C, // ordinal = 2
    D; // ordinal = 3
}

所以Type.D.compareTo(Type.A)的返回值就是3 - 0 = 3
虽然看起来有点意思,但是实际上有用吗?类的作者也考虑到了这一点,于是在注释上写了几笔:

简单来说就是,这玩意对绝大多数的码农来说没啥用,这个是设计给复杂的数据结构如EnumSetEnumMap使用的。

规范

在重写compareTo方法时,作者建议我们使用装箱类型自带的compare方法来替代“>”和“<”,如:Double.compareShort.compare,相对来说会更加简洁明朗。

另外书中作了一个引申,建议我们使用Compartor接口,因为可以更方便的进行一些操作,拿之前博客里面提到的PhoneNum举个例子:

public class PhoneNum implements Comparable<PhoneNum>{

	 /*区号*/
    private Short areaCode;

    /*号码*/
    private Integer num;

    /*分机号*/
    private Integer extensionNum;

	...
}

正常实现方式:

public int compareTo(PhoneNum other) {
        int result = Short.compare(areaCode, other.areaCode);
        if (result == 0) {
            result = Integer.compare(num, other.num);
            if (result == 0) {
                result = Integer.compare(extensionNum, other.extensionNum);
            }
        }
        return result;
    }

Compartor实现:

	// 先构造一个静态的 Comparator
    private static final Comparator<PhoneNum> COMPARATOR = Comparator
            .comparingInt((PhoneNum pn) -> pn.areaCode)
            .thenComparingInt(pn -> pn.num)
            .thenComparingInt(pn -> pn.extensionNum);
            
    public int compareTo(PhoneNum other) {
        return COMPARATOR.compare(this, other);
    }

如此,代码的质量肉眼可见提升了。

总结

对于一个有排序需求的类,为了让它可以轻松地进行分类、搜索以和用在基于比较的集合中,建议实现Comparable接口。在重写compareTo时,记得使用装箱基本类型自带的compare方法,对于逻辑较为复杂的逻辑,建议使用Comparator

举报

相关推荐

0 条评论