详解Comparable、Comparator、Cloneable接口介绍与使用

Comparable、Comparator、Cloneable接口介绍与使用

1、java.lang.Comparable

我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,之间使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢?

Java给所有引用数据类型的大小比较,指定了一个标准接口,就是java.lang.Comparable接口:

package java.lang;
public interface Comparable{
int compareTo(Object obj);
}

那么我们想要使得我们某个类的对象可以比较大小,怎么做呢?步骤:

第一步:哪个类的对象要比较大小,哪个类就实现java.lang.Comparable接口,并重写方法

  • 方法体就是你要如何比较当前对象和指定的另一个对象的大小

第二步:对象比较大小时,通过对象调用compareTo方法,根据方法的返回值决定谁大谁小。

  • this对象(调用compareTo方法的对象)大于指定对象(传入compareTo()的参数对象)返回正整数
  • this对象(调用compareTo方法的对象)小于指定对象(传入compareTo()的参数对象)返回负整数
  • this对象(调用compareTo方法的对象)等于指定对象(传入compareTo()的参数对象)返回零

2、java.util.Comparator

思考:

(1)如果一个类,没有实现Comparable接口,而这个类你又不方便修改(例如:一些第三方的类,你只有.class文件,没有源文件),那么这样类的对象也要比较大小怎么办?

(2)如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是此时此刻我不想按照它预定义的方法比较大小,但是我又不能随意修改,因为会影响其他地方的使用,怎么办?

JDK在设计类库之初,也考虑到这种情况了,所以又增加了一个java.util.Comparator接口。

package java.util;
public interface Comparator{
int compare(Object o1,Object o2);
}
那么我们想要比较某个类的两个对象的大小,怎么做呢?步骤:

第一步:编写一个类,我们称之为比较器类型,实现java.util.Comparator接口,并重写方法

  • 方法体就是你要如何指定的两个对象的大小

第二步:比较大小时,通过比较器类型的对象调用compare()方法,将要比较大小的两个对象作为compare方法的实参传入,根据方法的返回值决定谁大谁小。

  • o1对象大于o2返回正整数
  • o1对象小于o2返回负整数
  • o1对象等于o2返回零

3、java.lang.Cloneable

标记接口:没有任何方法的接口。类似注解。

在java.lang.Object类中有一个方法:

protected Object clone()throws CloneNotSupportedException

所有类型都可以重写这个方法,它是获取一个对象的克隆体对象用的,就是造一个和当前对象各种属性值一模一样的对象。当然地址肯定不同。

我们在重写这个方法后时,调用super.clone(),发现报异常CloneNotSupportedException,因为我们没有实现java.lang.Cloneable接口。

案例实现:

实体类:

public class Employee implements Comparable ,Cloneable{
    private String name;
    private int age;
    private double salary;

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public Employee() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }

    @Override
    public int compareTo(Object o) {
        Employee e = (Employee) o;
        int v = Double.compare( e.getSalary(),this.salary);
        v = v == 0 ? this.age - e.getAge() : v;
        v = v == 0 ? this.name.compareTo(e.getName()) : v;
        return v;
    }
     //实现cloneable接口须将权限修饰符改为public,
     //否则在其他类下无法访问此方法也就无法访问父类的clone方法,
     // protected只能被同一个类、包和其他包的子类调用
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

比较器类型

public class EmployeeComparator implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
        Employee e1 = (Employee) o1;
        Employee e2 = (Employee) o2;
        int v = Double.compare(e1.getSalary(), e2.getSalary());
        v = v == 0 ? e1.getAge() - e2.getAge() : v;
        v = v == 0 ? e1.getName().compareTo(e2.getName()) : v;
        return v;
    }
}

对象数组工具类

public class MyArraysTools {
    public static Object[] sort(Object[] arr) {
        //冒泡排序
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i; j++) {
                //将arr[j]强制为Comparable接口类型,目的是调用compareTo方法
                //当然如果数组的元素没有实现这个接口,那么将会发生ClassCastException
                Comparable c = (Comparable) arr[j];
                if (c.compareTo(arr[j + 1]) > 0) {
                    Object temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        return arr;
    }

    public static void print(Object[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

    public static Object[] sort(Object[] arr, Comparator comparator) {
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0; j < arr.length-1-i; j++) {
                if(comparator.compare(arr[j],arr[j+1])>0){
                    Object obj=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=obj;
                }
            }
        }

        return arr;
    }
}

测试类:

public class ComparableTest {
    public static void main(String[] args) {
        Employee[] employees = new Employee[4];
        employees[0]=new Employee("张三",18,20000);
        employees[1]=new Employee("李四",18,21000);
        employees[2]=new Employee("王五",19,22000);
        employees[3]=new Employee("赵六",33,50000);
        Object[] sort = MyArraysTools.sort(employees);
        MyArraysTools.print(sort);


    }
}

public class ComparatorTest {
    public static void main(String[] args) {
        Employee[] employees = new Employee[4];
        employees[0]=new Employee("张三丰",23,23000);
        employees[1]=new Employee("张无忌",33,33000);
        employees[2]=new Employee("乔峰",33,33000);
        employees[3]=new Employee("雷芷若",22,22000);
        EmployeeComparator employeeComparator = new EmployeeComparator();
        Object[] sort = MyArraysTools.sort(employees, employeeComparator);
        MyArraysTools.print(sort);
    }

}
public class CloneTest {
    public static void main(String[] args) throws CloneNotSupportedException {
        Employee employee = new Employee("张三",15,20000);
        Object clone = employee.clone();
        System.out.println(clone);

    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力奋斗的JAVA小余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值