java中对象的比较

文章详细介绍了Java中对象的比较方式,包括基本类型与引用类型的比较,以及`equals`方法的使用。接着讨论了`Comparable`接口,展示了如何实现`compareTo`方法来比较对象。此外,还解释了`Comparator`接口的作用,给出了不同场景下使用比较器的例子,如List排序和自定义比较逻辑。最后总结了比较和排序在编程中的重要性。
摘要由CSDN通过智能技术生成

目录

一、== 和 equals

1. 基本类型

2. 引用类型(对象的比较)

二、Comparable<> 接口

1. 实现了Comparable<> 接口的类的使用

2. 自己定义一个实现 Comparable<> 接口的类

三、Comparator<> 接口 (比较器)

1. List 中使用比较器

2. 本身数据类型具备比较能力,但不符合实际需求

3. 比较器对象也可作为参数传入指定方法(sort 排序方法)

四、总结


一、== 和 equals

1. 基本类型

< <= == != > >= 

2. 引用类型(对象的比较)

(1)引用1 == 引用2 为 true:引用1 和 引用2 都指向同一个对象。

   如:引用1 == 引用2 == null 为 true:两个引用都不指向任何对象。

(2)引用1 .equals(引用2) == true:引用1 指向的对象 和 引用2 指向的对象 是“相等的”。 

  前提:对象的类正确的重写了 equals 方法。

== : 关于同一性的比较

equals:关于相等性的比较 

二、Comparable<> 接口

  当要比较的对象是自定义的类的对象时,单纯的“大/小”不能进行判断。这时候就需要用到 Comparable<> 接口。

  要使用 Comparable<> 接口来进行比较,需要实现其 compareTo() 方法。

compareTo()方法:

int cmp = p1.compareTo(p2);

cmp < 0:p1 小于 p2

cmp = 0:p1 等于 p2

cmp > 0:p1 大于 p2

1. 实现了Comparable<> 接口的类的使用

public class Demo1 {
    public static void main1(String[] args) {
        String s = "hello";
        String t = "world";

        int cmp = s.compareTo(t);
        if (cmp < 0) {
            System.out.println(s + "小于" + t);
        } else if (cmp == 0) {
            System.out.println(s + "等于" + t);
        } else {
            System.out.println(s + "大于" + t);
        }
    }

    public static void main(String[] args) {
        Integer i = 1234;
        Integer j = 1238;

        //包装类会自动拆箱
        //自动调用 i.intValue() 和 j.intValue()
        int cmp = i.compareTo(j);
        if (cmp < 0) {
            System.out.println(i + "小于" + j);
        } else if (cmp == 0) {
            System.out.println(i + "等于" + j);
        } else {
            System.out.println(i + "大于" + j);
        }
    }
}

2. 自己定义一个实现 Comparable<> 接口的类

  定义一个 Person 类,有身高(height)、体重(weight)、成绩(score)、等级(level)四个属性。Person 类中需要实现 compareTo() 方法,如何实现需要根据具体的自己的规定。

(1)规定 level 大的“大”

public class Person implements Comparable<Person>{
    private final int weight;
    private final int height;
    private final int score;
    private final int level;

    public Person(int weight, int height, int score, int level) {
        this.weight = weight;
        this.height = height;
        this.score = score;
        this.level = level;
    }
    
    @Override
    public int compareTo(Person o) {
        int r = this.level - o.level;
        if (r < 0) {
            return -1;
        } else if (r == 0) {
            return 0;
        } else {
            return 1;
        }
        //可直接简写为 return this.level - o.level;
    }
}

(2)按照 level > score > weight > height 的优先级比较

public class Person implements Comparable<Person>{
    private final int weight;
    private final int height;
    private final int score;
    private final int level;

    public Person(int weight, int height, int score, int level) {
        this.weight = weight;
        this.height = height;
        this.score = score;
        this.level = level;
    }

    @Override
    public int compareTo(Person o) {
        int r = this.level - o.level;
        if (r != 0) {
            return r;
        }
        
        r = this.score - o.score;
        if (r != 0) {
            return r;
        }
        
        r = this.weight - o.weight;
        if (r != 0) {
            return r;
        }
        
        //如果代码执行到这里,说明 level、score、weight 都相等
        return this.height - o.height;
    }
  
}

(3)按照相应的权重:身高0.3、体重0.2、成绩0.5、等级0.4。综合分比较

public class Person implements Comparable<Person>{
    private final int weight;
    private final int height;
    private final int score;
    private final int level;

    public Person(int weight, int height, int score, int level) {
        this.weight = weight;
        this.height = height;
        this.score = score;
        this.level = level;
    }

    @Override
    public int compareTo(Person o) {
        double t =  this.height * 0.3 + this.weight * 0.2 + this.score * 0.5 + this.level * 0.4;
        double s =  this.height * 0.3 + this.weight * 0.2 + this.score * 0.5 + this.level * 0.4;

        if ( t < s) {
            return -1;
        } else if (t == s) {
            return 0;
        } else {
            return 1;
        }
    }
}

注意:当我们实现compareTo() 方法时,不仅要遵循需要遵循和 equals() 方法的统一。即

 a.compareTo(b) == 0     ->     a.equals(b) == true

 a.compareTo(b) != 0      ->     a.equals(b) == false

三、Comparator<> 接口 (比较器)

  在java中,不是所有类都实现了Comparable<>接口,如 List接口 以及 ArryList 类。因此有了 Comparator<>接口。该接口是一个比较器,因此如果要用该接口进行比较的话。需要有三个对象:

  • 天平对象(需要提前定义天平类)
  • 要比较的 o1 对象
  • 要比较的 o2 对象

  即当我们进行比较时,需要拿出来一个天平(比较器),就是天平对象。然后在天平两端放上我们要进行比较的 o1 对象和 o2 对象。

  如要使用Comparator<> 比较器进行比较,需要在天平类中实现 compare() 方法。

compare() 方法:

int cmp = 天平对象.compare(o1, o2);

cmp < 0:o1 小于 o2

cmp = 0:o1 等于 o2

cmp > 0:o1 大于 o2

   下面举几个使用例子

1. List 中使用比较器

  现有 List1 和 List2 两个存储 int 类型的链表,比较两个链表的大小(根据链表中的元素个数进行比较)。

  思路:要比较  List1 和 List2 的大小,需要先判断:List 类是否是 Comparable 接口的实现类 或者 List 接口是否是 Comparable 的子接口,如果都不是,则只能使用 Comparator 比较器。

  List 和 ArrayList 都和 Comparable 没有关系,所以使用比较器。

public class Demo1 {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();

        list1.add(1);
        list1.add(2);
        list1.add(3);
        list1.add(4);

        list2.add(3);
        list2.add(4);
        list2.add(5);

        Comparator<List<Integer>> 天平 = new 基于List的比较器();
        int cmp = 天平.compare(list1, list2);

        if (cmp < 0) {
            System.out.println("list1 小于 list2");
        } else if (cmp == 0) {
            System.out.println("list1 等于 list2");
        } else {
            System.out.println("list1 大于 list2");
        }

    }

    //比较器类
    static class 基于List的比较器 implements Comparator<List<Integer>> {
        @Override
        public int compare(List<Integer> o1, List<Integer> o2) {
            return o1.size() - o2.size();
        }
    }
}

2. 本身数据类型具备比较能力,但不符合实际需求

  例如天干的比较,甲、乙、丙、丁、戊、己、庚、辛、壬、癸进行比较。

  本身的数据类型为 char(Character),具备自然比较能力,但不符合实际比较需求,即甲 < 乙 < 丙 < 丁 < 戊 < 己 < 庚 < 辛 < 壬 < 癸。因此使用比较器进行比较。(这里只比较甲乙) 

public class Demo2 {
    public static void main(String[] args) {
        char c1 = '甲';
        char c2 = '乙';

        Comparator<Character> 天平 = new 基于天干的比较器();
        int cmp = 天平.compare(c1, c2);

        if (cmp < 0) {
            System.out.println(c1 + "小于" + c2);
        } else if (cmp == 0) {
            System.out.println(c1 + "等于" + c2);
        } else {
            System.out.println(c1 + "大于" + c2);
        }
    }

    static class 基于天干的比较器 implements Comparator<Character> {

        @Override
        public int compare(Character o1, Character o2) {
            if (o1.equals('甲')){
                if (o2.equals('甲')) {
                    return 0;
                } else {
                    // o1:甲   o2:乙   甲 < 乙
                    return -1;
                }
            } else {
                //此时 o1:乙
                if (o2.equals('乙')) {
                    return 0;
                } else {
                    // o1:乙   o2:甲   乙 > 甲
                    return 1;
                }
            }
        }
    }
}

3. 比较器对象也可作为参数传入指定方法(sort 排序方法)

    在使用 sort() 方法时(Arrays.sort() 或者 List.sort() 或者 Collections.sort() 方法),传入相应参数对象进行默认排序,该排序时根据自然顺序进行升序排序的。当自然顺序不能满足实际要求时,也可将比较器对象传入 sort 方法中,sort 就会按照比较器中的 compare() 方法进行比较排序。 

  例一:List 链表中存储的是汉字 "零", "一", "二", "三", "四", "五", "六", "七", "八", "九",但是顺序不确定,现在需要将乱序的汉字排序成该顺序。

public class Demo3 {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(
                "零", "一", "二", "三", "四", "五", "六", "七", "八", "九"
        );

        //将 s1 中的元素打乱
        Collections.shuffle(list);
        System.out.println(list);

        //直接使用 sort
        Collections.sort(list);
        System.out.println(list); //[一, 七, 三, 九, 二, 五, 八, 六, 四, 零] 不符合预期

        //传入比较器
        Comparator<String> c = new CustomComparator();
        list.sort(c);
        System.out.println(list); //[零, 一, 二, 三, 四, 五, 六, 七, 八, 九]
    }

    static class CustomComparator implements Comparator<String> {
        //将String 转换为 int,方便调用到 compare 方法中
        private int transfer(String s) {
            switch (s) {
                case "零": return 0;
                case "一": return 1;
                case "二": return 2;
                case "三": return 3;
                case "四": return 4;
                case "五": return 5;
                case "六": return 6;
                case "七": return 7;
                case "八": return 8;
                case "九": return 9;
                default: return -1;
            }
        }

        @Override
        public int compare(String o1, String o2) {
            return transfer(o1) - transfer(o2);
        }
    }

}

   例二:使用数组将学生对象存储了起来(Student 类是自己写的,其中属性有学号及身高),现在需要将数组中的学生按照学号/身高进行排序。

  Student类:

public class Student {
    public final int no;
    public final int height;

    public Student(int no, int height) {
        this.no = no;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Student{" +
                "no=" + no +
                ", height=" + height +
                '}';
    }
}

  具体实现:

public class Demo4 {
    public static void main(String[] args) {
        Student[] array = {
                new Student(5,170),
                new Student(9,175),
                new Student(1,160),
                new Student(3,180),
        };

        //当调用Arrays.sort(array)时,因为数组中元素类型没有自然顺序,所以会报错
        //Arrays.sort(array):要求元素类型具备自然顺序 && 自然顺序符合预期
//        Arrays.sort(array);

        //传入比较器
        Comparator<Student> c = new StudentsComparator();
        Arrays.sort(array,c);
        System.out.println(Arrays.toString(array));
    }

    static class StudentsComparator implements Comparator<Student> {

        @Override
        public int compare(Student o1, Student o2) {
            return o1.no - o2.no;
            //若按照身高排序,改为 o1.height - o2.height 即可。
        }
    }
}

四、总结

1. ==:关于同一性比较

2. equals:关于相等性比较

3. Comparable 接口:具备比较能力

(1)方法:int compareTo(T  o)

  • this < o:负数
  • this == o:0
  • this > o:正数

(2)使用角度:

  • 使用已经实现了 Comparable 接口的类 的对象进行比较 ;
  • 定义类的角度:正确的重写了 compraeTo 方法。

4. Comparator 接口:用于比较两个东西的比较器

(1)方法:int compare(T  o1, T  o2)

  • o1 < o2:负数
  • o1 == o2:0
  • o1 > o2:正数

 (2)使用角度:

要比较的两个对象的类,不具备自然顺序,没有实现过 Comparable 接口;

要比较的两个对象的类,具备自然顺序,但是它的自然顺序不符合我们预期。

(3)sort方法:

List 排序:

  • Collecations.sort(List  list);
  • Collections.sort(List  list, Comparator  c);
  • list.sort(Comparator c);

数组排序:

  • Arrays.sort(数组);
  • Arrays.sort(数组, Comparator  c);

   对象可以进行比较时很多后续操作的前提,比如:

  • 排序(要求 线性表中的元素是可以比较大小的)
  • 优先级队列(要求 放入优先级队列的元素时可以比较大小的,因为优先级队列的原理是堆)
  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值