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是一次性的
posted @ 2020-01-07 21:33  可爱的红领巾  阅读(355)  评论(0编辑  收藏  举报