java比较器 Comparable , Comparator
在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是一次性的