• java中Comparable和Comparator两种比较器的区别


     Comparable和Comparator接口都是为了对类进行比较,众所周知,诸如Integer,double等基本数据类型,java可以对他们进行比较,而对于类的比较,需要人工定义比较用到的字段比较逻辑。可以把Comparable理解为内部比较器,而Comparator是外部比较器,基本的写法如下:

    复制代码
    class Apple implements Comparable<Apple>{
        int id;
        double price;
    
        public Apple(int id, double price) {
            this.id = id;
            this.price = price;
        }
        public int compareTo(Apple o) {
            //return Double.compare(this.getPrice(),o.getPrice());
            if (Math.abs(this.price-o.price)<0.001)
                return 0;
            else
                return (o.price-this.price)>0?1:-1;
        }
        @Override
        public String toString() {
            return "Apple{" +
                    "id=" + id +
                    ", price=" + price +
                    '}';
        }
    }
    复制代码
    复制代码
    class AESComparator implements Comparator<Apple>{
    
        public int compare(Apple o1, Apple o2) {
            if (Math.abs(o1.price-o2.price)<0.001)
                return 0;
            else{
                return (o1.price-o2.price)>0?1:-1;
            }
        }
    }
    复制代码

      实现了Comparable接口的类需要实现compareTo()方法,传入一个外部参数进行比对,实现了Comparator接口的方法需要实现compare()方法,对外部传入的两个类进行比较,从而让外部方法在比较时调用。

      两者的区别是实现Comparator接口代码更加灵活,可以定义某个类的多个比较器,从而在排序时根据实际场景自由调用,而Comparable接口实现后便不能改动。两种接口的调用方式如下:

    复制代码
    class AESComparator implements Comparator<Apple>{
    
        public int compare(Apple o1, Apple o2) {
            if (Math.abs(o1.price-o2.price)<0.001)
                return 0;
            else{
                return (o1.price-o2.price)>0?1:-1;
            }
        }
    }
    class  DESComparator implements Comparator<Apple>{
    
        public int compare(Apple o1, Apple o2) {
            if (Math.abs(o1.price-o2.price)<0.001)
                return 0;
            else {
                return (o1.price-o2.price)>0?-1:1;
            }
        }
    }
    复制代码
    复制代码
    public static void main(String[] args) {
            Apple apple1 = new Apple(1,4.8);
            Apple apple2 = new Apple(2,5.9);
            Apple apple3 = new Apple(3,8.5);
            List<Apple> list = new ArrayList<Apple>();
            list.add(apple1);
            list.add(apple3);
            list.add(apple2);
            System.out.println("Comparable==========");
            System.out.printf("this list of apples: %s
    ",list);
            Collections.sort(list);
            System.out.printf("this list of apples: %s
    ",list);
            System.out.println("Comparator==========");
            System.out.printf("this list of apples: %s
    ",list);
            Collections.sort(list,new DESComparator());
            System.out.printf("this list of apples: %s
    ",list);
            Collections.sort(list,new AESComparator());
            System.out.printf("this list of apples: %s
    ",list);
    
        }
    }
    复制代码

      上述代码存在的问题,不能在比较器中进行double类型的减法操作,因为对于值比较大的double,减法操作容易导致值的溢出,java7对每一种包装类型的比较新增了compare()方法,改造后的代码如下:

    复制代码
    class Apple implements Comparable<Apple>{
        int id;
        double price;
    
        public Apple(int id, double price) {
            this.id = id;
            this.price = price;
        }
        public int compareTo(Apple o) {
            return Double.compare(this.price,o.price);
        }
        @Override
        public String toString() {
            return "Apple{" +
                    "id=" + id +
                    ", price=" + price +
                    '}';
        }
    }
    class AESComparator implements Comparator<Apple>{
    
        public int compare(Apple o1, Apple o2) {
            return Double.compare(o1.price,o2.price);
        }
    }
    class  DESComparator implements Comparator<Apple>{
    
        public int compare(Apple o1, Apple o2) {
            return Double.compare(o2.price,o1.price);
        }
    }
    复制代码

      查看Double.compare的源码如下

    复制代码
    public static int compare(double d1, double d2) {
            if (d1 < d2)
                return -1;           // Neither val is NaN, thisVal is smaller
            if (d1 > d2)
                return 1;            // Neither val is NaN, thisVal is larger
    
            // Cannot use doubleToRawLongBits because of possibility of NaNs.
            long thisBits    = Double.doubleToLongBits(d1);
            long anotherBits = Double.doubleToLongBits(d2);
            return (thisBits == anotherBits ?  0 : // Values are equal
                    (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
                            1));                          // (0.0, -0.0) or (NaN, !NaN)
        }
    复制代码
  • 相关阅读:
    国内使用kubeadm部署kubernetes的完整流程
    Paxos协议笔记
    【LLVM笔记】0x00 初识LLVM 链接类型
    TLS 1.0协议
    风险指针(Hazard Pointer) 内存空间共享模型
    LRU算法
    从.git文件夹探析git实现原理
    Python爬虫与一汽项目【三】爬取中国五矿集团采购平台
    Python爬虫与一汽项目【二】爬取中国东方电气集中采购平台
    Python爬虫与一汽项目【一】爬取中海油,邮政,国家电网问题总结
  • 原文地址:https://www.cnblogs.com/andywithu/p/7239613.html
Copyright © 2020-2023  润新知