在java中,比较运算符(> , < , >= , <= , == , !=)可用于基本数据类型之间的比较,当我们要对两个对象进行比较时,只可以用 != 或者==来判断这两个对象是不是指向了内存中的同一个位置。 那么当我们要对类对象按照某种特定的方式进行排序时,该怎么办?。
这里的某种特定的方式:比如说有好几个学生类对象,学生类中有身高,成绩,学号这些属性,对这些学生类对象进行排序的方式有好几种:按照学生的身高从高到低排序,或者是按照学生的成绩由高到低进行排序等等。
java提供了两种比较器来帮我们实现排序:Comapre接口和Comparator接口
实现Compar接口(自然排序):
Compare接口的使用 :
如果要对自定义的类进行排序,我们可以实现Comparable接口,并重compareTo()方法,在comparTo()方法中指明如何排序
像String,包装类已经实现了Comparable接口,重写了compareTo()方法,按照从小到大的顺序进行排序
重写compareTo(obj)的规则:
- 如果当前对象大于形参对象obj,返回正整数
- 如果当前对象小于形参对象obj,返回负整数
- 如果当前对象等于形参对象obj,返回0
import java.util.Arrays;
import java.util.Comparator;
//创建商品类,里面有商品价格,商品名两个私有属性
class Goods implements Comparable {
private String name;
private double price;
public Goods(){
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String toString() {
return "Goods{name = "+name+"price = "+price+"}"+'\n';
}
public String geNmae() {
return name;
}
public double getPrice() {
return price;
}
//重写compareTo(Objext o)方法,对商品的价格从低到高进行排序
public int compareTo(Object o) {
if(o instanceof Goods) {
Goods anothergood = (Goods)o;
if(this.price > anothergood.price) {
return 1;
//return Double.compare(this.price, anothergood.price);效果与上行是一样的
}else if(this.price < anothergood.price) {
return -1;
}else {
return this.name.compareTo(anothergood.name);
}
}
else {//如果传入的数据类型不是商品类对象,那么抛出异常
throw new RuntimeException("传入的数据类型不一致!");
}
}
}
public class CompareTest_01 {
public static void main(String[] args) {
Goods[] arrs = new Goods[6];
arrs[0] = new Goods("levonomouse" , 55);
arrs[1] = new Goods("dellmouse" , 45);
arrs[2] = new Goods("xiaomimouse" , 70);
arrs[3] = new Goods("applemouse" , 33);
arrs[4] = new Goods("applemouse" , 343);
arrs[5] = new Goods("huaweimouse" , 70);
Arrays.sort(arrs);
System.out.println(Arrays.toString(arrs));
}
}
Comparator接口(定制排序):
为什么要Comparator接口:
- 当元素类型没有实现java.lang.Comparable接口而又不方便修改代码
- 实现了java.lang.Comparable接口的排序顺序不符合当前的操作需求,比如已经实现了Compareable接口的String类,但是我们又不要字符串按照从小到大的方式进行排序
重写compare(Object o1 , Object o2)方法,比较o1和o2的大小:
如果方法返回正值:表示o1>o2
如果方法返回负值:表示o1<o2
如果返回0:说明o1与o2相等
辅助类Array中有一个方法sort( T[] a , Comparator() comparator ),这个方法需要传入两个参数:需要进行排序的集合a,和一个实现Comparator接口的类对象。
package Compare_test;
import java.util.Arrays;
import java.util.Comparator;
class Goods implements Comparable {
private String name;
private double price;
public Goods(){
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String toString() {
return "Goods{name = "+name+"price = "+price+"}"+'\n';
}
public String geNmae() {
return name;
}
public double getPrice() {
return price;
}
}
//创建实现Comparator接口的类,指明商品的排序方式:先按照商品名从低到高排序,再按照商品价格从高到低排序
class GoodsComparator implements Comparator{
public int compare(Object o1, Object o2) {
if(o1 instanceof Goods && o2 instanceof Goods) {
Goods g1 = (Goods) o1;
Goods g2 = (Goods) o2;
return g1.geNmae().compareTo(g2.geNmae())==0? -Double.compare(g1.getPrice(), g2.getPrice()): g1.geNmae().compareTo(g2.geNmae());
}else
throw new RuntimeException("传入的两个数据类型不一致!");
}
}
public class CompareTest_02 {
public static void main(String[] args) {
Goods[] arrs = new Goods[6];
arrs[0] = new Goods("levonomouse" , 55);
arrs[1] = new Goods("dellmouse" , 45);
arrs[2] = new Goods("xiaomimouse" , 70);
arrs[3] = new Goods("applemouse" , 33);
arrs[4] = new Goods("applemouse" , 343);
arrs[5] = new Goods("huaweimouse" , 70);
GoodsComparator gc = new GoodsComparator();
Arrays.sort(arrs,gc);
System.out.println(Arrays.toString(arrs));
}
}
我们还可以使用匿名内部类的方式来实现comapare(Object o1 , Object o2)方法:
//指明商品的排序方式:先按照商品名从低到高排序,再按照商品价格从高到低排序
Arrays.sort(arrs, new Comparator() {
public int compare(Object o1 , Object o2) {
if(o1 instanceof Goods && o2 instanceof Goods) {
Goods g1 = (Goods) o1;
Goods g2 = (Goods) o2;
return g1.geNmae().compareTo(g2.geNmae())==0? -Double.compare(g1.getPrice(), g2.getPrice()): g1.geNmae().compareTo(g2.geNmae());
}else
throw new RuntimeException("传入的两个数据类型不一致!");
}
});
总结:Comparator更灵活
- Comaparbale接口(重写compareTo(Object obj)方法)的排序方式一旦确定,就保证了Comaparbale接口实现类的对象在任何位置都能按照指定的顺序排序
- Comparator接口(重写compare(Object o1 ,Object o2)方法)属于临时性的比较,在需要时就创建一个临时的匿名内部类,在里面定义排序的规则