编程语言
首页 > 编程语言> > 【Effective Java 14】考虑实现 Comparable 接口

【Effective Java 14】考虑实现 Comparable 接口

作者:互联网

1. 什么时候应该让类实现 Comparable 接口

Comparable 接口是一个泛型接口,代码如下:

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

类实现 Comparable 接口,就表明它的实例具有内在的排序关系,比如按照字母顺序、按数值顺序或者按年代顺序,那你就应该考虑实现 Comparable 接口:

一般来说,值类适合实现 Comparable 接口。

2. 使用 Comparable 接口的约定

将一个对象与另一个对象进行比较时。当对象小于、等于或大于指定对象的时候,分别返回一个负整数、零或正整数。如果由于指定对象的类型而无法与该对象进行比较,则抛出 ClassCastException 异常。

实现 Comparable 接口的类,在实现时应该满足以下约定(注意,在下面的说明中,符号 sgn(...) 表示数学中的 signum 函数,它根据表达式的值为负、零、正,分别返回-1,0,1):

注意,Comparable 接口不能跨越不同类型进行比较,在比较不同类型的对象时,可以在 compareTo 函数中抛出 ClassCastException 异常来拒绝执行。

违反 Comparable 接口约定会破坏其他依赖于比较关系的类或方法,如 TreeSetTreeMap、工具类 CollectionsArrays,因为它们内部都用与排序相关的算法。

3. 使用 Comparable 接口的建议

// 太繁琐
public int compare(Integer A, Integer B) {
    if A > B {
        return 1;
    } else if A < B {
        return -1;
    } else {
        return 0;
    }
}

// 有溢出风险
public int compare(Integer A, Integer B) {
	return A - B;
}

// 最佳
public int compare(Integer A, Integer B) {
	return Integer.compare(A, B);
}

4. 使用 Comparator 接口

private static class PhoneNumber implements Comparable<PhoneNumber>{
    private final short areaCode;
    private final short prefix;
    private final short lineNum;

    public PhoneNumber(short areaCode, short prefix, short lineNum) {
        this.areaCode = areaCode;
        this.prefix = prefix;
        this.lineNum = lineNum;
    }

    // 使用 Comparator 可以轻松实现对关键域按优先级进行比较
    private static final Comparator<PhoneNumber> COMPARATOR =
            Comparator
                    .comparingInt((ToIntFunction<PhoneNumber>) value -> value.areaCode)
                    .thenComparingInt(value -> value.prefix)
                    .thenComparingInt(value -> value.lineNum);

    @Override
    public int compareTo(PhoneNumber o) {
        return COMPARATOR.compare(this, o);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PhoneNumber that = (PhoneNumber) o;
        return areaCode == that.areaCode && prefix == that.prefix && lineNum == that.lineNum;
    }

    @Override
    public int hashCode() {
        return Objects.hash(areaCode, prefix, lineNum);
    }
}

5. 总结

标签:Comparable,return,14,Integer,接口,prefix,compareTo,Java
来源: https://www.cnblogs.com/Silgm/p/16142123.html