当前位置: 代码迷 >> 综合 >> 面试官:三年经验连 Comparable 和 Comparator 都不知道?
  详细解决方案

面试官:三年经验连 Comparable 和 Comparator 都不知道?

热度:4   发布时间:2024-02-11 05:34:20.0

在我们实际开发过程中,经常会遇到各种各样的排序,我们都知道,基本数据类型排序就是按照数值大小排序。

如果我们需要按照对象的某一个属性进行对象的比较排序,比如,按照商品的价格对商品进行排序,或者按照学生的升高对学生进行排序,这就涉及到对象间的排序。
应该怎么做呢?

一、自然排序:java.lang.Comparable

java.lang包下的Comparable接口会强行对他的实现类进行排序,这种排序规则称之为类的自然排序。例如String类,以及基本数据类型的包装类如IntegerDouble等都实现了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;}@Overridepublic String toString() {return "Product{" +"productName='" + productName + '\'' +", price=" + price +'}';}@Overridepublic 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>{/*** 定制年龄比较器*/@Overridepublic 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>{/*** 定制身高比较器*/@Overridepublic 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() {}@Overridepublic 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!强烈推荐。

  相关解决方案