在我们实际开发过程中,经常会遇到各种各样的排序,我们都知道,基本数据类型排序就是按照数值大小排序。
如果我们需要按照对象的某一个属性进行对象的比较排序,比如,按照商品的价格对商品进行排序,或者按照学生的升高对学生进行排序,这就涉及到对象间的排序。
应该怎么做呢?
一、自然排序:java.lang.Comparable
java.lang包下的Comparable接口会强行对他的实现类进行排序,这种排序规则称之为类的自然排序。例如String类,以及基本数据类型的包装类如Integer,Double等都实现了Comparable接口并重写了**compareTo()**方法。默认都是有小到大排序。
如果我们需要对自定义对象进行排序,则需要实现Comparable 接口 并重写compareTo()方法,对象间通过conpareTo的返回值进行大小比较,如果大于当前对象则返回整数一般为 1
,如果小于当前对象 则返回负数,一般为 -1
,如果相等则 返回 0
。
另外实现了,Comparable 接口的对象都可以使用Arrays.sort(),以及Collections.sort()方法进行排序。
import java.util.Arrays;
class test {
public static void main(String[] args) {
Product products [] = new Product[4];
Product product = new Product("A",12d);
products[0] = product;
Product product1 = new Product("B",10d);
products[1] = product1;
Product product2 = new Product("C",18d);
products[2] = product2;
Product product3 = new Product("D",1d);
products[3] = product3;
int i = product.compareTo(product1);
System.out.println("比较结果:"+i);
System.out.println("排序前:"+Arrays.toString(products));
Arrays.sort(products);
System.out.println("排序后:"+Arrays.toString(products));
}
}
public class Product implements Comparable<Product>{
private String productName;
private Double price;
public Product(String productName, Double price) {
this.productName = productName;
this.price = price;
}
public Product() {
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Product{" +
"productName='" + productName + '\'' +
", price=" + price +
'}';
}
@Override
public int compareTo(Product o) {
if(this.price>o.price){
return 1;
}else if(this.price<o.price){
return -1;
}else{
return 0;
}
}
}
上面我们在compareTo方法里对price进行排序。当前对象price大于传入对象price则为1
,小于则为-1
,等于则为0
; 可以看到使用 Arrays.sort(products);
进行对象排序也是可以的。
比较结果:1
排序前:[Product{productName='A', price=12.0}, Product{productName='B', price=10.0}, Product{productName='C', price=18.0}, Product{productName='D', price=1.0}]
排序后:[Product{productName='D', price=1.0}, Product{productName='B', price=10.0}, Product{productName='A', price=12.0}, Product{productName='C', price=18.0}]
二、定制排序:java.util.Comparator
如果当前对象并没有实现Comparable接口,我们又不想对原有代码进行改动,可以考虑使用Comparator强行对多个对象进行整体排序。
相当于构建了一个比较器,对多个对象进行比较排序。我们无需对原有代码进行改动,只需要对相应的对象,专门构建一个Comprator比较器,在进行数据排序的时候,只需要将比较器传递Arrays.sort()或者Collections.sort()方法即可。
排序规则也可以定制化,可以创建一个价格比较器,也可以创建一个重量比较器等。
import java.util.Arrays;
import java.util.Comparator;
class Test{
public static void main(String[] args) {
Student students[] = new Student[4];
students[0] = new Student("张三",22,165.8d);
students[1] = new Student("李四",28,176.8d);
students[2] = new Student("王五",19,188.8d);
students[3] = new Student("赵六",20,166.8d);
Arrays.sort(students,new AgeComparator());
System.out.println("按年龄排序:"+Arrays.toString(students));
Arrays.sort(students,new HeightComparator());
System.out.println("按身高排序:"+Arrays.toString(students));
}
}
class AgeComparator implements Comparator<Student>{
/**
* 定制年龄比较器
*/
@Override
public int compare(Student o1, Student o2) {
if(o1.getAge()>o2.getAge()){
return 1;
}else if(o1.getAge()<o2.getAge()){
return -1;
}else{
return 0;
}
}
}
class HeightComparator implements Comparator<Student>{
/**
* 定制身高比较器
*/
@Override
public int compare(Student o1, Student o2) {
if(o1.getHeight()>o2.getHeight()){
return 1;
}else if(o1.getHeight()<o2.getHeight()){
return -1;
}else{
return 0;
}
}
}
public class Student {
private String name;
private int age;
private double height;
public Student(String name, int age, double height) {
this.name = name;
this.age = age;
this.height = height;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}
Student 有age和height两个属性都可以排序,我们分别定制一个年龄排序AgeComparator
,和身高排序HeightComparator
。
按年龄排序:[Student{name='王五', age=19, height=188.8}, Student{name='赵六', age=20, height=166.8}, Student{name='张三', age=22, height=165.8}, Student{name='李四', age=28, height=176.8}]
按身高排序:[Student{name='张三', age=22, height=165.8}, Student{name='赵六', age=20, height=166.8}, Student{name='李四', age=28, height=176.8}, Student{name='王五', age=19, height=188.8}]
我么将不同的Comparator 交给 Arrays.sort()将会得到不同的排序结果。扩展性很强,侵入性小。
总结
1.使用Comparable接口进行排序时,需要对对象本身进行操作,实现Comparable接口并重写compareTo()方法,对代码侵入性较大,耦合度高。不推荐使用。
2.使用Comparator接口进行排序时,无需变动对象本身,侵入性小,耦合度低,同时还具有多样性,可以定制多种排序规则。nice!强烈推荐。