在日常测试中,经常碰到如何对自己定义的类的对象按照某种方式进行比较排序的问题。比如,我自己定义一个Fish类,然后按照每个Fish对象的属性:age,进行排序。
下边是自定义的Fish类(其中的构造方法对每个属性都进行了随机性的初始化,其中age,随机在[1,3)中;price,随机在[10,20),color,随机一个枚举类(Color)中的颜色):
import java.util.Random;
public class Fish implements Comparable<Fish>{
private int age;
private Color color;
private int price;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public static int ran_age(int min,int max) {
Random ran=new Random();
int num=min+ran.nextInt(max-min);
return num;
}
public static Color ran_col() {
Color[] col=Color.values();
int num=ran_age(0, col.length);
return col[num];
}
public Fish() {
setAge(ran_age(1, 3));
setColor(ran_col());
setPrice(ran_age(10, 20));
}
@Override
public String toString() {
return "Fish [age=" + age + ", color=" + color + ", price=" + price + "]"+"\n";
}
@Override
public int compareTo(Fish o) {
return this.getAge()-o.getAge();//按照对象的age属性进行排序
}
}
下面是一个颜色(color)的枚举类:</span>
public enum Color {
RED,ORANGE,YELLOW,GREEN,BLUE,CYAN,PURPLE;
}
另外,自己定义一个测试类(TestFish.java):具体内容是,新建一个数组,保存了5个Fish类的对象,然后按照每个对象的年龄进行自然排序。
import java.util.Arrays;
public class TestFish {
public static void main(String[] args) {
Fish f1=new Fish();
Fish f2=new Fish();
Fish f3=new Fish();
Fish f4=new Fish();
Fish f0=new Fish();
Fish[] fi=new Fish[5];
fi[0]=f0;
fi[1]=f1;
fi[2]=f2;
fi[3]=f3;
fi[4]=f4;
Arrays.sort(fi);
System.out.println("数组类型输出:");
for (Fish fish : fi) {
System.out.println(fish);
}
}
}
结果为:
数组类型输出:
Fish [age=1, color=YELLOW, price=13]
Fish [age=1, color=BLUE, price=10]
Fish [age=2, color=YELLOW, price=13]
Fish [age=2, color=GREEN, price=11]
Fish [age=2, color=CYAN, price=13]
如上所示,按照每一个Fish的age属性进行自然排序。其中,调用了Arrays.sort(Object[] a)的方法,在API中,对此方法的解释是:
public static void sort(Object[] a)
根据元素的自然顺序对指定对象数组按升序进行排序。数组中的所有元素都必须实现 Comparable 接口。此外,数组中的所有元素都必须是可相互比较的(也就是说,对于数
组中的任何 e1 和 e2 元素而言,e1.compareTo(e2) 不得抛出 ClassCastException)。
因此,我们如果想把某个自定义类的对象按照某种属性来进行排序,就让此类实现Comparable接口,重写里边的compareTo方法即可,这在java中,称为:内部比较器。
还有一种外部比较器,就是让自己定义的类去实现Comparator这个接口,重写其中的compare方法。或者,用匿名内部类来实现,拿本例来讲,在测试类中,就不能再用原来的Arrays.sort(Object[] a)方法了,可以用Arrays.sort(T[] a,Comparator<? super T> c)方法,在API中:
public static <T> void sort(T[] a, Comparator<? super T> c)
根据指定比较器产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过指定比较器可相互比较的(也就是说,对于数组中的任何 e1 和 e2
c.compare(e1, e2) 不得抛出 ClassCastException)。
那么,在测试类中怎么写呢?别急,看下边(将上述中代码中“Arrays.sort(fi));”直接改为如下代码即可:
Arrays.sort(fi, new Comparator<Fish>() {
@Override
public int compare(Fish o1, Fish o2) {
return o1.getAge()-o2.getAge();
}
});
那么结果为:
总结来说,如果想对自定义类的对象按照某种属性来排序的话,第一种:内部比较器,让自定义类去实现Comparable接口,并实现其中的compareTo方法即可。第二种,
外部比较器,实现Comparator接口,实现其中的compare方法即可。