在java中经常会涉及到对对象数组的排序问题,那么就涉及到对象之间的比较问题,
但是在java的对象中正常情况下只能使用 ==, != 不可使用 >, < 来比较两个对象的大小, 但是在开发中要比较对象的大小时,比较器就顺势而生了
在java中我们常用的比较器有:
自然排序: Comparable
定制排序: Comparator
自然排序: Comparable
Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称 为类的自然排序。
实现Comparable类必须实现它的compareTo(Object obj)方法 ,也就是比较的内容要放在compareTo(Object obj)方法中实现
Comparable 的典型实现:(默认都是从小到大排列的)
String:按照字符串中字符的Unicode值进行比较
Character:按照字符的Unicode值来进行比较
数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值 大小进行比较
Boolean:true 对应的包装类实例大于 false 对应的包装类实例 Date、Time等:后面的日期时间比前面的日期时间大
实现compareTo(Object obj)的结果
重写compareTo()的规则:
如果当前对象this大于形参对象obj,则返回正整数
如果当前对象this小于形参对象obj,则返回负整数
如果当前对象this等于形参对象obj,则返回0
package Compare;
import java.util.Arrays;
public class ComparableTestTwo {
public static void main(String[] args) {
GoodsTestTwo [] arr = new GoodsTestTwo[3];
arr[0] = new GoodsTestTwo("老王",123);
arr[1] = new GoodsTestTwo("老张",121);
arr[2] = new GoodsTestTwo("老刘",110);
Arrays.sort(arr); // 先排序
System.out.println(Arrays.toString(arr)); // 再求值 [GoodsTestTwo{name='老刘', price=110.0}, GoodsTestTwo{name='老张', price=121.0}, GoodsTestTwo{name='老王', price=123.0}]
}
}
class GoodsTestTwo implements Comparable{
@Override
public int compareTo(Object o){ // 实现Comparable 接口的compareTo()
if(o instanceof GoodsTestTwo){ // 判断是否是同一种类型
GoodsTestTwo goodsO = (GoodsTestTwo) o; // 进行类型转化
// 方式一
if(this.price > goodsO.price){
return 1;
}else if(this.price < goodsO.price){
return -1;
}else{ // 相等
return 0;
// return this.name.compareTo(goodsO.name); //如果相等就按照其名字排序
}
// 方式一结束, 方式二开始
// return Double.compare(this.price,goodsO.price); // 点开源码看到方式一就是其源码实现过程
// 想获得从大到小的值 就修改为 return Double.compare(this.price,goodsO.price);
}
throw new RuntimeException("输入的有误");
}
private String name;
private double 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;
}
public GoodsTestTwo(){};
public GoodsTestTwo (String name, double price){
this.name = name;
this.price = price;
}
@Override
public String toString() {
return "GoodsTestTwo{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
上面的求值的时候如果想获取从大到小的值就改为:
想获得从大到小的值 就修改为 return Double.compare(this.price,goodsO.price);
定制排序 : Comparator
当元素的类型没有实现Comparable接口自然排序时 或者实现了Comparable自然排序但是排序规则不适应本身时 可以使用Comparator定制排序,
强行对多个对象进行整体排序
排序要求:
重写compare(Object obj, Object obj2) 比较obj1 和obj2的大小如果方法返回为正整数,则是obj1大如果方法返回为负整数 则是obj2大为0则是两者相同
重写Compare(Object obj1, Object obj2)方法比较obj1和obj2
如果返回正整数 则表示obj1 大于obj2
如果返回负整数则obj2 大于obj1
如果返回0两者相等
eg:
public class ComparatorTestOne {
public static void main(String[] args) {
String[] arr = new String[]{"AA", "CC", "KK", "MM", "GG", "JJ"};
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof String && o2 instanceof String) {
String str1 = (String) o1;
String str2 = (String) o2;
return -str1.compareTo(str2);
}
throw new RuntimeException("输入有误");
}
});
System.out.println(Arrays.toString(arr)); // [MM, KK, JJ, GG, CC, AA]
// ==========
GoodsTest [] arry = new GoodsTest[5];
arry[0] = new GoodsTest("laowang",123);
arry[1] = new GoodsTest("laozhang",103);
arry[2] = new GoodsTest("laoli",100);
arry[3] = new GoodsTest("laoliu",113);
arry[4] = new GoodsTest("laohong",78);
// 先安装名字从低到高 再按照价格 从高到底
Arrays.sort(arry, new Comparator(){
@Override
public int compare(Object obj1, Object obj2){
if(obj1 instanceof GoodsTest && obj2 instanceof GoodsTest){
GoodsTest goodsTestOne = (GoodsTest) obj1;
GoodsTest goodsTestTwo = (GoodsTest) obj2;
if(((GoodsTest) obj1).getName().equals(((GoodsTest) obj2).getName())){
return -Double.compare(((GoodsTest) obj1).getPrice(),((GoodsTest) obj2).getPrice());
}else{
// return ((GoodsTest) obj1).getName().compareTo(((GoodsTest) obj2).getName());
return -Double.compare(((GoodsTest) obj1).getPrice(), ((GoodsTest) obj2).getPrice());
}
}
throw new RuntimeException("输入的不对");
}
});
System.out.println(Arrays.toString(arry));
// [GoodsTest{name='laowang', price=123.0}, GoodsTest{name='laoliu', price=113.0}, GoodsTest{name='laozhang', price=103.0}, GoodsTest{name='laoli', price=100.0}, GoodsTest{name='laohong', price=78.0}]
}
}
class GoodsTest {
private String name;
private double price;
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "GoodsTest{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
public GoodsTest(){}
public GoodsTest(String name, double price){
this.name = name;
this.price = price;
}
}
自然排序 和定制排序的区别:
Comparable 一旦指定 可以保证 它的实现类再任何位置都可以进行比较
Comparator 接口属于临时性的只在实现位置进行比较
两者好比一次性筷子和非临时性筷子的区别
Comparator是一次性的