【1】java.lang.Comparable
Comparable,翻译一下为可比较的。从汉语词义来看,通常是表明对象特性,即该对象是可比较的。实现了该接口的类的实例对象就可以进行自然排序,该实例对象的集合或者数组就可以使用Collections.sort或Arrays.sort方法进行自然排序。
接口源码如下:
package java.lang; import java.util.*; public interface Comparable<T> { int compareTo(T var1); }
实现了该接口的类实例对象可以作为SortedMap的key或者SortedSet的元素,而无需使用一个额外的比较器-Comparator。
强烈推荐自然排序结果与equals方法保持一致(虽然不是一定的),即自然排序时两个对象相等条件为 e1.equals(e2)返回true时,e1.compareTo(e2) == 0。另外需要注意的是null对象不是任何一个类的实例对象,所以e.compareTo(null)应该抛出NullPointerException,即使e.equals(null)返回false。
如果compareTo方法与对象的equals方法比较结果不一致时 ,那么在使用SortedMap、SortedSet这类没有明确比较器的集合时就会很奇怪。尤其是将会违反集合的基本约定–根据equals方法判断集合元素是否相等。
然而并不 严格要求(x.compareTo(y)==0) == (x.equals(y))。一般说来,任何违背这个条件的实现都应该明确指出这一事实情况。
实际上,实现Comparable的所有Java核心类都具有与equals一致的自然顺序。一个例外是java.math.BigDecimal,其自然顺序等同于具有相同值和不同精度(例如4.0和4.00)的大十进制对象。
int compareTo(T var1);方法会比较两个实例对象,0表示相等,正数表示大于,负数表示小于。
实现该方法一定要注意以下事项:
必须保证sgn(x.compareTo(y)) ==-sgn(y.compareTo(x)) 。
必须保证比较的顺序关系是可传递的,如果x.compareTo(y)>0 而且y.compareTo(z)>0 则x.compareTo(z)>0。
如果存在x.compareTo(y)=0,则对于 z 而言,存在 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。
Comparable 的典型实现:
BigDecimal、BigInteger 以及所有的数值型对应的包装类:按它们对应的数值大小进行比较
Character:按字符的 unicode值来进行比较
Boolean:true 对应的包装类实例大于 false 对应的包装类实例
String:按字符串中字符的 unicode 值进行比较
Date、Time:后边的时间、日期比前面的时间、日期大
【2】java.util.Comparator
首先第一点不同的就是,包不同了!Comparable是在java.lang包中,而Comparator是在java.util中。
第二点不同的是Comparator被显示作为一个函数式接口,其上有@FunctionalInterface注解。其只有两个抽象方法(compare和equals)但是提供了很多默认方法和静态方法。
Java 8中允许接口中包含具有具体实现的方法,该方法称为“默认方法”,默认方法使用default关键字修饰。而且Default方法只在接口中被允许使用。
Java8 中,接口中允许添加静态方法,可以直接被使用。
package java.util; import java.io.Serializable; import java.util.function.Function; import java.util.function.ToIntFunction; import java.util.function.ToLongFunction; import java.util.function.ToDoubleFunction; import java.util.Comparators; @FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); default Comparator<T> reversed() { return Collections.reverseOrder(this); } //... }
Comparator比较器可以被使用在Collections.sort或 Arrays.sort方法中允许对排序顺序进行精确控制。Comparator同样可以被使用在SortedSet、SortedMap以及对其他自身没有自然排序属性的实例对象上。
同Comparable一样,Comparator的compare方法返回结果应该与equals方法返回结果保持一致。即,c.compare(e1, e2)==0时e1.equals(e2)。
不过建议谨慎使用Comparator,因为该比较器可以强制排序与使用equals方法排序集合不一致。
实现Comparator的compare方法需要保证以下几点:
必须保证sgn(compare(x, y)) ==-sgn(compare(y, x))
必须保证比较的顺序关系是可传递的,如果compare(x,y)>0 而且compare(y,z)>0 则 compare(x,z)>0。
如果存在 compare(x,y)=0,则对于 z 而言,存在 compare(x, z)==compare(y, z)。
强烈推荐compare(x,y)方法返回结果与x.equals(y)方法返回结果保持一致。然而并不 严格要求(compare(x, y)==0) == (x.equals(y))。一般说来,任何违背这个条件的 Comparator 实现都应该明确指出这一事实情况。
—
使用实例如下
@Test public void test4(){ List<Integer> integers=new ArrayList<>(); integers.add(1); integers.add(2); integers.add(3); //匿名内部类 integers.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1.compareTo(o2); } }); //lambda表达式 integers.sort((o1,o2)->o1.compareTo(o2)); // Comparator<Integer> integerComparator = Integer::compareTo; //方法引用 integers.sort(Integer::compareTo); integers.sort(Comparator.comparing(Integer::intValue)); }