Java中对象排序的两种方式:
1.实现Comparable接口
2.实现Comparator接口
其中Comparable在java.lang包下,Comparator在java.util包下,这两种方式具体实现方法和应用场景如下:
1.Collections的sort()方法要求被排序对象必须实现Comparable接口并重写其中的compareTo()方法
package test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
class Person1 implements Comparable<Person1>{
String name;
int age;
public Person1(String name,int age) {
this.age = age;
this.name = name;
}
@Override
public String toString(){
return name + age;
}
@Override
public int compareTo(Person1 other){
if(this.name != other.name) return this.name.compareTo(other.name);
else return this.age - other.age;
}
}
public class ComparableTest {
public static void main(String[] args) {
List<Person1> persons = Arrays.asList(
new Person1("tom", 25),
new Person1("frank", 27),
new Person1("tom", 20)
) ;
Collections.sort(persons);
System.out.println(persons);
}
}
2.有了Comparable为什么还要有Comparator呢?
上面的代码中Person1对象操作了Comparable接口,但如果你的对象无法操作Comparable呢?也许你拿不到原始码,也许你不能修改原始码。举个例子,我们现在对String排序,String本身有操作Comparable,但默认的String排序是按照字典序从小到大,今天你想让排序结果反过来从大到小怎么办?修改String.java里的comparaTo()方法?这方法明显不可行,就算你修改后重新编译为String.class放回rt.jar中,也只有你的JRE能用,这已经不是标准API了。继承String重新定义compareTo()方法?也不可能,因为String声明为final,不能被继承。
Collections的sort()方法有另一个重载版本,可接受Comparator接口的操作对象(通常称作比较器),如果使用这个版本,排序方式将根据Comparator的compare()定义来决定。我们这里还是按照Person类的排序。
package test;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Person2{
String name;
int age;
public Person2(String name,int age) {
this.age = age;
this.name = name;
}
@Override
public String toString(){
return name + age;
}
}
class PersonComparator implements Comparator<Person2>{
@Override
public int compare(Person2 o1, Person2 o2) {
if(o1.name != o2.name) return o1.name.compareTo(o2.name);
else return o1.age - o2.age;
}
}
public class ComparatorTest {
public static void main(String[] args) {
List<Person2> persons = Arrays.asList(
new Person2("tom", 25),
new Person2("frank", 27),
new Person2("tom", 20)
) ;
Collections.sort(persons, new PersonComparator());
System.out.println(persons);
}
}
从代码中可以看出我们唯一需要做的就是增加一个名为PersonComparator的比较器,把上面代码中Person1中的比较规则放进去,然后在Collections.sort中创建比较器实例,这样可以在不能操作对象源代码的情况下实现对象排序。
JDK8在List上增加了sort()方法,可接受Comparator实例来指定排序方式,因此以上代码可以通过Lambda表达式简化为
package test;
import java.util.Arrays;
import java.util.List;
class Person3{
String name;
int age;
public Person3(String name,int age) {
this.age = age;
this.name = name;
}
@Override
public String toString(){
return name + age;
}
}
public class LambdaComparator {
public static void main(String[] args) {
List<Person3> persons = Arrays.asList(
new Person3("tom", 25),
new Person3("frank", 27),
new Person3("tom", 20)
) ;
persons.sort((o1,o2) -> {
if(o1.name != o2.name) return o1.name.compareTo(o2.name);
else return o1.age - o2.age;
});
System.out.println(persons);
}
}