1.Comparable接口
Arrays类中的sort方法可以对对象数组进行排序,但是对象所属的类必须实现Comparable接口。
下面是一个例子
对象数组按score排序
package com.fu.demo;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,50);
a[1]=new A(2,90);
a[2]=new A(4,80);
a[3]=new A(3,70);
Arrays.sort(a);
for (A aa:a) {
System.out.println(aa);
}
}
}
class A implements Comparable<A>{
private int num;
private double score;
public A(int num, double score) {
this.num = num;
this.score = score;
}
@Override
public int compareTo(A o) {
return Double.compare(score,o.score);
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
'}';
}
}
2.Comparator接口
在下面这个例子中,sort对String数组按字典顺序排序。这是因为String实现了Comparable接口,若此时我们需求改变了,我们需要对String按长度排序怎么办?这里我们就可以引入Comparator接口了。
import java.util.Arrays;
import java.util.Date;
public class Test {
public static void main(String[] args) {
String[] arr={
"bbb","aa","c","dddd"};
for (String str:arr) {
System.out.println(str);
}
Arrays.sort(arr);
for (String str:arr) {
System.out.println(str);
}
}
}
sort的重载方法的第二个参数是传一个比较器,比较器就是实现了Comparator接口的类的实例。我们来看一个例子,按字符串长度排序。
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test2 {
public static void main(String[] args) {
String[] array={
"bbb","aa","c","dddd"};
for (String str:array) {
System.out.println(str);
}
Arrays.sort(array,new LengthComparator());
for (String str:array) {
System.out.println(str);
}
}
}
//这个类的实例就是比较器
class LengthComparator implements Comparator<String>{
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
}
此外,Comparator接口还有很多静态方法。这些静态方法很方便去创建比较器。
静态comparing方法取一个“键提取器”函数,它将类型T映射为一个可比较的类型。对要比较的对象应用这个函数,然后对返回的键完成比较。
下面用静态方法按score排序
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,50);
a[1]=new A(2,90);
a[2]=new A(4,80);
a[3]=new A(3,70);
for (A aa:a) {
System.out.println(aa);
}
Arrays.sort(a,Comparator.comparing(A::getNum));//按num排序
for (A aa:a) {
System.out.println(aa);
}
}
}
class A{
private int num;
private double score;
public A() {
}
public A(int num, double score) {
this.num = num;
this.score = score;
}
public int getNum() {
return num;
}
public double getScore() {
return score;
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
'}';
}
}
与手动实现一个Comparator相比,这当然容易得多。而且代码也更清晰。
我们还可以把比较器与thenComparing方法串行起来,来处理比较结果相同的情况。例如:
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,50);
a[1]=new A(3,90);
a[2]=new A(4,80);
a[3]=new A(3,70);
for (A aa:a) {
System.out.println(aa);
}
Arrays.sort(a,Comparator.comparing(A::getNum).thenComparing(A::getScore));
//先按num排序,再按score
for (A aa:a) {
System.out.println(aa);
}
}
}
class A{
private int num;
private double score;
public A() {
}
public A(int num, double score) {
this.num = num;
this.score = score;
}
public int getNum() {
return num;
}
public double getScore() {
return score;
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
'}';
}
}
这些方法有很多变体。可以为comparing和thencomparing方法提取的键指定一个比较器。例如,根据先根据按长度排序,再按字典顺序排序。
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test2 {
public static void main(String[] args) {
String[] array={
"bb","aa","c","dddd"};
for (String str:array) {
System.out.println(str);
}
Arrays.sort(array,Comparator.comparing(String::length).thenComparing(String::compareTo));
for (String str:array) {
System.out.println(str);
}
}
}
先按名字长度排序,再按score排序
package com.fu.demo;
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
A[] a=new A[4];
a[0]=new A(1,100,"aa");
a[1]=new A(3,90,"bb");
a[2]=new A(4,80,"ddddddddd");
a[3]=new A(3,70,"cccc");
for (A aa:a) {
System.out.println(aa);
}
Arrays.sort(a,Comparator.comparing(A::getName,(s,t)->s.length()-t.length()).thenComparing(A::getScore));
//先按名字长度排序,再按score排序
for (A aa:a) {
System.out.println(aa);
}
}
}
class A{
private int num;
private double score;
private String name;
public A() {
}
public A(int num, double score, String name) {
this.num = num;
this.score = score;
this.name = name;
}
public String getName() {
return name;
}
public int getNum() {
return num;
}
public double getScore() {
return score;
}
@Override
public String toString() {
return "A{" +
"num=" + num +
", score=" + score +
", name='" + name + '\'' +
'}';
}
}
还有别的静态方法,Comparator.comparingInt,nullsFirst等,都可以查询api,然后调用就好。