在 Java 中经常会涉及到对象数组的排序问题,那么久涉及到对象之间的比较问题
实现对象排序的方式有两种:
自然排序: java.lang.Comparable
定制排序: java.util.Comparator
Comparable接口:自然排序
Comparable接口的使用举例
比如 String 、 包装类等都实现了Comparable
接口,重写了compareTo(Object obj)
方法,给出了比较两个对象大小的方式
注意以下代码中。
当数组使用Array.sort(数组)
、集合使用Collection.sort(集合)
方法的时候,默认会调用方法中传递的实参重写的compareTo(Object obj)
方法。
若传入的实参没有实现Comparable 接口重写compareTo(Object obj)方法,会报错。因为不知道根据什么样的规则去进行排序
public class Test {
public static void main(String[] args) {
String[] arr = new String[]{"DD","AA","BB","WW","SS","QQ"};
//调用工具类Array中的排序方法,此方法中会调用参数对象的compareTo()方法
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
重写compareTo(Object obj)
的规则:
如果当前对象 this 大于形参对象 obj ,返回正整数
如果当前对象 this 小于形参对象 obj ,返回负整数
如果当前对象 this 等于形参对象 obj ,返回0
对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable
接口,重写compareTo(Object obj)
方法,在compareTo(Object obj)
方法中指明如何排序
public class Test{
public static void main(String[] args) {
Goods[] arr = new Goods[5];
arr[0] = new Goods("MM",22);
arr[1] = new Goods("AA",99);
arr[2] = new Goods("KK",22);
arr[3] = new Goods("FF",55);
arr[4] = new Goods("VV",44);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}
class Goods implements Comparable{
private String name;
private double price;
public Goods(){}
public void setPrice(int a) {price = a;}
public double getPrice(){return price;}
public void setName(String name) {this.name = name;}
public double getName(){return name;}
//重写compareTo()方法
//按照价格从低到高排序
public int compareTo(Object obj){
if(obj instanceOf Goods){
//方式一:
Goods gg = (Goods)obj;
if(this.price > gg.price){
return 1;
}else if(this.price < gg.price){
return -1;
}else{
return 0;
}
//方式二:
//return Double.compare(this.price,gg.price);
}
throw new RuntimeException("传入的数据类型不对");
}
}
按照价格从低到高排序,再根据商品名称从高到低排序
注意: String 、 包装类等已经被重写的compareTo(Object obj)
方法默认是从低到高
排序
public int compareTo(Object obj){
//按照价格从低到高排序,再根据商品名称从高到低排序
if(obj instanceOf Goods){
//方式一:
Goods gg = (Goods)obj;
if(this.price > gg.price){
return 1;
}else if(this.price < gg.price){
return -1;
}else{
return -this.name.compareTo(gg.name);
}
//方式二:
//return Double.compare(this.price,gg.price);
}
throw new RuntimeException("传入的数据类型不对");
}
Comparator接口:定制排序
实现Comparator
接口,重写compare(Object o1,Object o2)
方法
什么情况下使用:
当元素的类型没有重写compareTo(Object obj)
方法,或者写了compareTo(Object obj)
方法但是并不够,还需要另外的一种排序方法
重写compare(Object o1,Object o2)
的规则:
若方法返回正整数,则表示 o1
大于o2
若返回0,则表示相等
若但会负整数,则表示 o1
小于o2
class Untitled {
public static void main(String[] args) {
String[] arr = new String{"vv","gg","xx","aa","ee"};
//根据字符串从大到小排序
Arrays.sort(arr,new Comparator(){
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);
}
throw new RuntimeException("传入的数据类型不对");
}
});
System.out.println(Arrays.toString(arr));
}
}
现在在用上面商品的例子
class Untitled {
public static void main(String[] args) {
Goods[] arr = new Goods[5];
arr[0] = new Goods("MM",22);
arr[1] = new Goods("AA",99);
arr[2] = new Goods("KK",22);
arr[3] = new Goods("FF",55);
arr[4] = new Goods("VV",44);
//根据商品名称从低到高排序,再根据价格从高到低排序
Arrays.sort(arr,new comparator(){
public int compare(Object o1,Object o2){
if(o1 instanceOf Goods && o2 instanceOf Goods){
Goods s1 = (Goods)o1;
Goods s2 = (Goods)o2;
if(s1.getName.equals(s2.getName)){
return -Double.compare(s1.getPrice,s2.getPrice);
}else{
//return String.compare(s1.getName,s2.getName);
return s1.getName.compareTo(s2.getName);
}
}
throw new RuntimeException("传入的数据类型不对");
}
});
System.out.println(Arrays.toString(arr));
}
}
class Goods{
private String name;
private double price;
public Goods(){}
public void setPrice(int a) {price = a;}
public double getPrice(){return price;}
public void setName(String name) {this.name = name;}
public double getName(){return name;}
}
小结
- 自然排序:实现
Comparable
接口,重写compareTo(Object obj)
方法- 调用方法的对象与传入的对象进行比较
- 重写
compareTo(Object obj)
的规则:
如果当前对象this
大于形参对象obj
,返回正整数 - String 、 包装类等都重写
compareTo(Object obj)
方法,是从低到高的排序 - 默认是从低到高,需要从高到低就写个负号
- 定制排序:使用
Comparator
接口,重写compare(Object o1,Object o2)
方法- 重写
compare(Object o1,Object o2)
的规则:
若方法返回正整数,则表示o1
大于o2
- 默认是从低到高,需要从高到低就写个负号
- 重写
Comparable
接口与使用Comparator
对比Comparable
接口的方式一旦确定,保证Comparable
接口实现类的对象在任何位置都可以比较大小Comparator
接口属于临时性的比较