背景:
当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码(比如JDK当中的类),或者实现了java.lang.Comparable接口,但定义好的排序规则不适合当前的操作,那么可以考虑使用接口Comparator 的对象来排序,强行对多个对象进行整体排序的比较。
定制的含义: 按照需求去指定排序规则
接口中的抽象方法:
int compare(T o1,T o2);T指的是泛型,这个方法是让两个形参对象去比较大小。
重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
如果方法返回正整数,则表示o1大于o2
如果返回0,表示相等
返回负整数,表示 o1小于o2
需要在compare中指明o1和o2按照什么规则比较
注意:
可以将 Comparator传递给sort方法(如 Collections.sort或Arrays.sort), 从而允许在排序顺序上实现精确控制。还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的顺序,或者为那些没有自然顺序的对象 collection 提供排序。
注意:静态方法不能重写
需要创建接口实现类的对象,因为实现类也就用一次,所以可以采用匿名的方式创建
package test01;
import java.util.Arrays;
import java.util.Comparator;
public class Test{
public static void main(String[] args) {
String[] arr=new String[] {"AA","CC","KK","MM","GG","JJ","DD"};
//Arrays.sort(arr);//这么干是按照从小到大排序
Arrays.sort(arr,new Comparator() {
//按照字符串从大到小的顺序排列
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof String&&o2 instanceof String) {
String s1=(String)o1;
String s2=(String)o2;
//return s1.compareTo(s2);这样又成了从小到大
return -s1.compareTo(s2);
}
throw new RuntimeException("输入数据的类型不一致");
}
});
System.out.println(Arrays.toString(arr));//[MM, KK, JJ, GG, DD, CC, AA]
}
}
定义自定义类的情况
package test01;
import java.util.Arrays;
import java.util.Comparator;
public class Test{
public static void main(String[] args) {
Goods[] arr=new Goods[5];
arr[0]=new Goods("lenovoMouse", 34);
arr[1]=new Goods("dellMouse", 43);
arr[2]=new Goods("xiaomiMouse", 12);
arr[3]=new Goods("huaweiMouse", 65);
arr[4]=new Goods("microsoftMouse", 43);
//Arrays.sort(arr);//这里还是按照自然排序来进行的
//现在要求按照按产品名称从低到高排序,名称相同的情况下按照价格从高到低排序
Arrays.sort(arr,new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Goods&&o2 instanceof Goods) {
Goods g1=(Goods)o1;
Goods g2=(Goods)o2;
if(g1.getName().equals(g2.getName())) {
//如果名字一样再按照价格从高到低排列
return -Double.compare(g1.getPrice(), g2.getPrice());//因为该方法如果第一个参数大于第二个参数,返回的是1,第二个参数大于第一个参数返回-1,所以也是从低到高的顺序排的,因为我们现在想让价格从高往低排序,所以前面加上-
}else {
return g1.getName().compareTo(g2.getName());
}
}
throw new RuntimeException("输入数据的类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
}
class Goods implements Comparable{
private String name;
private double price;
public Goods() {
super();
}
public Goods(String name, double price) {
super();
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods [name=" + name + ", price=" + price + "]";
}
//指明商品按照什么方式进行排序:按照价格从低到高,再按照产品名称从高到低排序(当两者价格相同的情况下才从高到低)
@Override
public int compareTo(Object o) {
if(o instanceof Goods) {
Goods goods=(Goods)o;
if(this.price>goods.price) {
return 1;
}else if(this.price<goods.price) {
return -1;
}else {
//return 0;
return -this.name.compareTo(goods.name);//注意-号
}
}
throw new RuntimeException("传入的数据类型不一致");
}
}
实现对象比较大小的两种方式的对比:
Comparator是调用sort方法时临时给出的排序方式
Comparable更像是一劳永逸,以后凡是在调用sort的时候只要没有用Comparator都是这么排序
Comparable接口的方式一旦指定,可以保证Comparable接口的实现类在任何位置都可以比较大小,Comparator则是临时性的比较