JavaSE的三大接口:Comparator,Comparable和Cloneable詳解
進階JavaSE-三大接口:Comparator、Comparable和Cloneable。
Comparable和Comparator這兩個接口很相似,都是用于比較大小的接口。在我們寫一些數(shù)據(jù)結構的算法題時,用的比較多,具體是怎么用的,我們接著往下看。
Comparator接口:
public interface Comparator<T> {
public int compare(T o1, T o2); //比較方法
}
Comparable接口:
public interface Comparable<T> {
public int compareTo(T o);
}
在具體實現(xiàn)的類中,實現(xiàn)Comparable接口,然后在類里面重新compareTo方法,就能這個類具有可比較的能力,在添加完數(shù)據(jù)后,可以直接調用Collections.sort() 或者Arrays.sort() 方法,就能對裝有這個類的對象的集合進行排序。
而Comparator接口,是不需要在被排序對象的類中實現(xiàn)這個接口的,這個接口是自己單獨實現(xiàn)一個類,實現(xiàn)這個接口。然后調用Collections.sort(),或者其他方法,就可以將被排序的集合和這個接口一起傳過去,就能實現(xiàn)排序。
Comparator接口:自己單獨實現(xiàn)排序類。不需要在被排序的類中實現(xiàn)。
Comparable接口:必須在被排序的類中實現(xiàn)這個接口。
上訴兩個接口實現(xiàn)后,都需要重寫相應的比較方法。
具體實例:
//Comparator接口實例
class Student {
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return this.name + " " + this.age;
}
}
public class Demo {
//實現(xiàn)Comparator接口的類
private static class AgeCompare implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age; //以年齡進行排序
}
}
public static void main(String[] args) {
Student student1 = new Student("小明", 10);
Student student2 = new Student("小剛", 5);
Student student3 = new Student("彭于晏", 28);
Student student4 = new Student("胡歌", 26);
Student[] array = new Student[4];
array[0] = student1;
array[1] = student2;
array[2] = student3;
array[3] = student4;
System.out.println("排序前: " + Arrays.toString(array));
Arrays.sort(array, new AgeCompare()); //以年齡進行排序
System.out.println("排序后: " + Arrays.toString(array));
}
}
最后輸出的結果:

Comparable接口示例:
//Comparable接口示例
class Student implements Comparable<Student>{
public String name;
public int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return this.name + " " + this.age;
}
@Override
public int compareTo(Student o) {
return this.name.compareTo(o.name); //以姓名進行排序
}
}
public class Demo2 {
public static void main(String[] args) {
Student student1 = new Student("Tom", 10);
Student student2 = new Student("Emma", 5);
Student student3 = new Student("Alice", 20);
Student student4 = new Student("Kate", 30);
Student[] array = new Student[4];
array[0] = student1;
array[1] = student2;
array[2] = student3;
array[3] = student4;
System.out.println("排序前:" + Arrays.toString(array));
Arrays.sort(array); //以姓名進行排序
System.out.println("排序后:" + Arrays.toString(array));
}
}
最終輸出結果:

注:String類里面的CompareTo方法,是按照字典序的大小進行比較。簡單點說,每個字符都有相應的ASCII碼值,這個方法會從頭開始比較每個字符,如果前者小于后者,返回-1,相等返回0,大于就返回1。具體的注釋可以查看幫助文檔。
以上就是兩個比較接口的使用,這兩接口通常也叫做比較器。
Cloneable接口:用于克隆的。

也就是說,一個類要想實現(xiàn)克隆的功能,需要實現(xiàn)Cloneable接口,實現(xiàn)這個接口后,還必須自己手動的書寫Object的clone方法。
切記:在沒有實現(xiàn)接口的情況下,調用克隆方法,會拋出異常。
Cloneable示例:

通過person對象,調用克隆方法,就能實現(xiàn)克隆。那么問題來了,這是深拷貝還是淺拷貝?關于深拷貝淺拷貝,我前面有一篇文章講過
深拷貝與淺拷貝。
我們來看下面這一段代碼,可能你就會更好理解這個Cloneable接口:

上訴代碼所對應的內存圖如下:

此時如果我們通過person1來改變money里面的值,那么person對象里面的也會被修改。因為本質上這兩個對象的money值是指向同一塊空間的。這也就是淺拷貝。
那么要實現(xiàn)深拷貝,該如何?
那就將money對象,再拷貝一份出來,讓person1的money值指向新的空間即可。
class Money implements Cloneable {
public int number;
public Money(int number) {
this.number = number;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
public String name = "Tom";
public Money money = new Money(100);
@Override
protected Object clone() throws CloneNotSupportedException {
Person clone = (Person) super.clone();
clone.money = (Money) this.money.clone();
return clone;
}
}
public class Demo3 {
public static void main(String[] args) throws CloneNotSupportedException {
Person person = new Person();
Person person1 = (Person)person.clone(); //調用person對象的克隆方法
System.out.println(person.name + " " + person.money.number);
System.out.println("===========");
person1.money.number = 20;
System.out.println(person1.name + " " + person1.money.number);
}
}
運行結果:

注意一下,Person類里面克隆方法的修改,并且Money類也是需要實現(xiàn)Cloneable接口的。

切記,Cloneable接口是一個空的接口,也叫標記接口。這個接口的存在,只是為了證明當前這個類是有克隆方法。如果不寫這個接口,調用克隆方法,會報異常。
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
Java中關于內存泄漏出現(xiàn)的原因匯總及如何避免內存泄漏(超詳細版)
這篇文章主要介紹了Java中關于內存泄漏出現(xiàn)的原因匯總及如何避免內存泄漏(超詳細版)的相關資料,需要的朋友可以參考下2016-09-09
Spring Cloud Gateway 內存溢出的解決方案
這篇文章主要介紹了Spring Cloud Gateway 內存溢出的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
Spring?Boot中WebMvcConfig配置詳解及示例代碼
WebMvcConfig是一個配置類,它繼承了WebMvcConfigurationSupport,允許我們對SpringMVC進行更細粒度的控制,這篇文章主要給大家介紹了關于Spring?Boot中WebMvcConfig配置詳解及示例的相關資料,需要的朋友可以參考下2024-03-03
springcloud 中 zuul 修改請求參數(shù)信息的方法
這篇文章主要介紹了springcloud 中 zuul 修改請求參數(shù)信息的方法,需要的朋友可以參考下2018-02-02
java實現(xiàn)列表、集合與數(shù)組之間轉化的方法
這篇文章主要介紹了java實現(xiàn)列表、集合與數(shù)組之間轉化的方法,涉及java中列表、集合與數(shù)組相互轉換的技巧,非常具有實用價值,需要的朋友可以參考下2015-03-03

