Comparable使用
Comparable只是一個簡單的接口,
public interface Comparable<T> {
public int compareTo(T o);
}
使用如下:
public class Person implements Comparable<Person> {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Person o) {
return this.age - o.age;
}
@Override
public String toString() {
return "age=" + age + ", name='" + name;
}
public static void main(String[] args) {
List<Person> list = Arrays.asList(new Person[]{new Person(23, "Merry"),
new Person(18, "Jack"),
new Person(25, "Lx")});
Collections.sort(list);
System.out.println(list.toString());
}
}
Comparator源碼如下
Comparator在Java8中是一個函數式接口,除去原始的jdk7中保留的equals
和compare
方法,還添加了部分針對java8函數式編程添加的default
和static
方法。
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
/**
* 返回一個倒序比較器
*/
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
/**
* 返回二次比較器
*/
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
/**
* 根據給定的關鍵字抽取函數返回二次比較器
*/
default <U> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
return thenComparing(comparing(keyExtractor, keyComparator));
}
default <U extends Comparable<? super U>> Comparator<T> thenComparing(
Function<? super T, ? extends U> keyExtractor)
{
return thenComparing(comparing(keyExtractor));
}
/**
* 根據整形關鍵字抽取起返回二次比較器
*
*/
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
/**
* Returns a lexicographic-order comparator with a function that
* extracts a {@code long} sort key.
*/
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
return Collections.reverseOrder();
}
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
}
/**
* 返回非空的比較器
*/
public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(true, comparator);
}
public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
return new Comparators.NullComparator<>(false, comparator);
}
/**
* Accepts a function that extracts a sort key from a type {@code T}, and
* returns a {@code Comparator<T>} that compares by that sort key using
*/
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
{
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
}
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
}
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
}
}
Comparator使用方式如下
對一個學生列表,實現按照年齡順序,成績倒序的排序,實現如下:
public class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
}
@Data
public class Student {
String name;
int age;
double score;
public Student(String name, int age, float score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}'+"\n";
}
public static void main(String[] args) {
List<Student> list = Arrays.asList(new Student[]{new Student("lx", 27, 99.5f),
new Student("xs", 26, 89.5f),
new Student("mj", 25, 92.5f),
new Student("lx2", 27, 79.5f),
new Student("xs2", 26, 79.5f),
new Student("mj2", 25, 62.5f)}
);
//二次排序採用傳入Lamda表達式的方式
Collections.sort(list, new StudentComparator().thenComparing((s1,s2)->(int)(s2.score-s2.score)));
System.out.println(list.toString());
}
}
執行結果如下:
[Student{name='mj', age=25, score=92.5}
, Student{name='mj2', age=25, score=62.5}
, Student{name='xs', age=26, score=89.5}
, Student{name='xs2', age=26, score=79.5}
, Student{name='lx', age=27, score=99.5}
, Student{name='lx2', age=27, score=79.5}
]
Comparator與Comparable的比較
相同點
- 都是用於比較兩個對象“順序”的接口
- 都可以使用Collections.sort()方法來對對象集合進行排序
不同點
- Comparable位於java.lang包下,而Comparator則位於java.util包下
- Comparable 是在集合內部定義的方法實現的排序,Comparator 是在集合外部實現的排序
- 使用Comparable接口來實現對象之間的比較時,可以使這個類型(設爲A)實現Comparable接口,並可以使用Collections.sort()方法來對A類型的List進行排序,之後可以通過a1.comparaTo(a2)來比較兩個對象;
當使用Comparator接口來實現對象之間的比較時,只需要創建一個實現Comparator接口的比較器(設爲AComparator),並將其傳給Collections.sort()方法即可對A類型的List進行排序,之後也可以通過調用比較器AComparator.compare(a1, a2)來比較兩個對象。例如上面的二次排序問題;
可以說一個是自己完成比較,一個是外部程序實現比較的差別而已。用Comparator 是策略模式(strategy design pattern),就是不改變對象自身,而用一個策略對象(strategy object)來改變它的行爲。