Java比较器

Java比较器,第1张

Java比较器

目录

总结

Comparable接口

String、包装类都实现了Comparable接口,并且重写了其中的compareTo(obj)方法

 自定义类重写compareTo(obj)的规则

Comparator接口:定制排序


总结

只要是需要对象比较大小,就需要用到Comparable或者Comparator接口

Comparable中的compareTo方法 Comparator中的compare方法都最终反馈给Arrays中的sort方法进行排序,因此两个比较方法返回的值都是int,让sort处理返回的int

Comparable接口
  1. Comparable接口的形参一定是Object o
  2. Comparable接口的返回值一定是int
  3. Comparable接口尽量不要返回 数字a-数字b
  4. 不可省略implements Comparable              虽然真正实现比较的是compareTo方法,但如果不写implements Comparable而直接自行写一个compareTo方法的逻辑是会报错的,这是由规范决定的:比较的目的是用sort方法排序,而sort方法用的是compareTo方法的结果。作为开发者没有必要为了不写implements Comparable而重复定义sort方法
String、包装类都实现了Comparable接口,并且重写了其中的compareTo(obj)方法

例如:

"aa".compareTo("bb")返回的结果是-1,意为"aa"-"bb"=-1<0即"aa"<"bb"

"cc".compareTo("bb")返回的结果是1,意为"cc"-"bb"=1>0即"cc">"bb"

"bb".compareTo("bb")返回的结果是0,意为"aa"-"bb"=0即"bb"="bb"

Q:为什么不直接返回aa-bb?最后用sort方法判断>0 <0 ==0?

A:假如是比较double类型的aa和bb,1.9 - 1.2 = 0.7的结果最终会转为int类型,因此返回一个强转后的0值,则会导致错误排序为aa=bb

 String类中重写了compareTo()方法,返回-1、1、0结果,然后Arrays中的sort()来处理返回值结果

 自定义类重写compareTo(obj)的规则

实现Comparable接口则必须重写compareTo方法

  • 如果当前this对象 > 形参对象obj,则返回正数
  • 如果当前this对象 = 形参对象obj,则返回0
  • 如果当前this对象 < 形参对象obj,则返回正数

如果把正负对应的颠倒,则使用sort后排序顺序也颠倒

 因为形参一定是Object o,所以在重写compareTo方法的时候需要对形参对象类型先进行判断,同类型的话在进行比较

比较对象的数字属性

Sting、包装类 本质上就是比较数字属性,并且比较自定义类的时候,本质上也要落实到比较数字属性

包装类本身也定义了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)
    }
return Double.compare(this.price,g.price);
            //包装类都能用compare方法

 但在比较复杂对象的时候尽量不要用该方法,最好用if语句挨个列出

比较对象的其他属性

 例如:创建一个Goods商品类,属性有商品名和价格,比较价格高低

public class compareTest {

    public static void main(String[] args) {
        Goods g1 = new Goods("黑丝", 40);
        Goods g2 = new Goods("白丝", 30);
        Goods g3 = new Goods("肉丝", 35);
        Goods g4 = new Goods("蕾丝", 35);
        Goods[] arr = new Goods[]{g1, g2, g3, g4};
        Arrays.sort(arr);
        for(Goods goods:arr){
            System.out.println(goods);
        }
    }
}

class Goods implements Comparable {
    String name;
    double price;

    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + ''' +
                ", price=" + price +
                '}';
    }

  
    public Goods(String name, double price) {
        this.name = name;
        this.price = price;


    }

    @Override
    public int compareTo(Object o) {
        if (o instanceof Goods) {
            Goods g = (Goods) o;
            if (this.price > g.price) {
                return 1;
            }
            if (this.price < g.price) {
                return -1;
            }
            // if (this.price == g.price) {
            //其他属性的比较逻辑
            //略
        else {
            return 0;
        }
        }
        else{
            throw new RuntimeException("类型不一致");
        }
    }


}
Comparator接口:定制排序

使用背景:

  1. 没有实现java.lang.Comparable接口而又不方便修改代码的
  2. 虽实现了java.lang.Comparable接口但排序规则不合适的

使用方法:

  1. 不用implements Comparable接口,也不用在类定义中重写compareTo方法
  2. 直接使用sort方法进行排序,由于sort方法有另一个构造器,其形参为(数组,Comparator对象),定制比较方法包含在Comparator中
  3. 定制排序一般都是只用一次,所以用匿名对象+匿名方法
        Goods[] arr = new Goods[]{g1, g2, g3, g4};
//*********************在形参中创建匿名对象*****************
//*********************其逻辑体现在compare方法中***********
        Arrays.sort(arr, new Comparator() {
            @Override
            public int compare(Goods o1, Goods o2) {
                                if (o1 instanceof Goods&&o2 instanceof Goods) {
                    Goods g1 = (Goods) o1;
                    Goods g2 = (Goods) o2;
                    if (o2.price > o1.price) {
                        return 1;
                    }
                    if (o2.price < o1.price) {
                        return -1;
                    }
                    // if (this.price == g.price) {
                    //其他属性的比较逻辑
                    //略
                    else {
                        return 0;
                    }
        }
        else{
            throw new RuntimeException("类型不一致");
        }
            }
        });
        for(Goods goods:arr){
            System.out.println(goods);
        }
 

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/3979783.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-10-21
下一篇 2022-10-21

发表评论

登录后才能评论

评论列表(0条)

保存