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);
}
}