从源码出发:JAVA中对象的比较
?前言?
📘 博客主頁:to Keep博客主頁
🙆歡迎關(guān)注,👍點(diǎn)贊,📝留言評論
?首發(fā)時(shí)間:2022年2月26日
📨 博主碼云地址:博主碼云地址
📕參考書籍:java核心技術(shù) 卷1
📢編程練習(xí):牛客網(wǎng)+力扣網(wǎng)
由于博主目前也是處于一個(gè)學(xué)習(xí)的狀態(tài),如有講的不對的地方,請一定聯(lián)系我予以改正!!!
文章目錄
- 📕 PriorityQueue(優(yōu)先級隊(duì)列)自定義類型對象的比較
- 📘 Comparable接口進(jìn)行比較
- 📖 實(shí)現(xiàn)Comparable接口
- 📖源碼分析
- 📙 Comparator比較器進(jìn)行比較
- 📖 構(gòu)造Comparator比較器
- 📖 源碼分析
- 📖 匿名內(nèi)部類的方式
- 📒 覆寫基類中的equals
- 📖注意事項(xiàng):
- 📖缺陷:
- 🔓 總結(jié)
📕 PriorityQueue(優(yōu)先級隊(duì)列)自定義類型對象的比較
在前面一遍文章中,我們了解到了什么是堆,為了簡單理解起見我們采用了基本數(shù)據(jù)類型(Integer)去進(jìn)行比較,下面我們通過代碼來分析是如何實(shí)現(xiàn)自定義的類型進(jìn)行比較。
我們首先定義一個(gè)學(xué)生類:
比較的結(jié)果:
之前我們了解到,優(yōu)先級隊(duì)列的底層其實(shí)就是一個(gè)堆,我們?yōu)榱藵M足堆的性質(zhì),我們必須進(jìn)行元素的比較,而我們自定義類型是無法直接比較的,需要我們通過指定的方法進(jìn)行比較的。那么我們只有通過以下幾種方式進(jìn)行自定義類型的比較!
📘 Comparable接口進(jìn)行比較
📖 實(shí)現(xiàn)Comparable接口
我們首先必須先要在自定義類型中讓它實(shí)現(xiàn)Comparable接口,重寫comparable方法
public class Student implements Comparable<Student>{public int ID;public String name;public Student(int Id,String name){this.ID = Id;//學(xué)號this.name=name;//姓名}@Overridepublic int compareTo(Student o) {return this.ID-o.ID;}@Overridepublic String toString() {return "Student{" +"ID=" + ID +", name='" + name + '\'' +'}';} } class priority{public static void main(String[] args) {PriorityQueue<Student> priorityQueue = new PriorityQueue<>();Student student1 = new Student(1,"1號");Student student2 = new Student(2,"2號");priorityQueue.offer(student1);priorityQueue.offer(student2);System.out.println(priorityQueue);}}運(yùn)行結(jié)果:
📖源碼分析
從以上的結(jié)果我們可以看出,這時(shí)候我們自定義的student1和student2兩個(gè)對象可以進(jìn)行比較,下面我們通過源碼來分析以下是如何比較的:
首先,添加一個(gè)元素,源碼中的E表示的是泛型,這個(gè)之后我們會(huì)詳細(xì)講解,第一次傳過來的是student1,student1肯定不等于null,(modCount++無關(guān)我們分析),然后源碼中size=0;所以i是為0的,下一步判斷是否超過數(shù)組長度(因?yàn)閮?yōu)先級隊(duì)列底層就是一個(gè)數(shù)組)
如果超過了長度,原容量如果小于64,那么就會(huì)使2*oldcapacity+2擴(kuò)容,否則就是1.5倍的擴(kuò)容
然后此時(shí)size=1,由于i是為0的,那么就直接把student1直接放到queue[0]的位置
此時(shí)在加入student2,那么以上的執(zhí)行步驟是一樣的,只不過student2放進(jìn)來的時(shí)候i是不等于0的,所以只能執(zhí)行else語句,else語句之后就會(huì)來到下列方法,而一開始的時(shí)候就將comparator置為null,所以只能執(zhí)行else語句。
來到else語句之后將進(jìn)行以下操作,先將student2強(qiáng)轉(zhuǎn)為可比較的類型,此時(shí)k是由i傳參過來的,那么k為1,e取出queue[0]中的值,也就是student1,符合if語句中的比較方式(也就是利用重寫comparable中student2中的學(xué)號減去student1中的學(xué)號差值),那么此時(shí)將會(huì)直接跳出循環(huán),不進(jìn)行交換,所以queue[1]=student2的值
📙 Comparator比較器進(jìn)行比較
📖 構(gòu)造Comparator比較器
class ID implements Comparator<Student>{@Overridepublic int compare(Student o1, Student o2) {return o1.ID-o2.ID;} } class priority{public static void main(String[] args) {ID id = new ID();PriorityQueue<Student> priorityQueue = new PriorityQueue<>(id);Student student1 = new Student(1,"1號");Student student2 = new Student(2,"2號");priorityQueue.offer(student1);priorityQueue.offer(student2);System.out.println(priorityQueue);}}注意這里在利用Comparator構(gòu)造時(shí),是需要添加比較器的引用的,否則Comparator默認(rèn)為null,這樣的話是不能利用Comparator進(jìn)行比較。
📖 源碼分析
經(jīng)過對Comparatable源碼分析,其實(shí)Comparator的分析也是差不多的,就是在shifUp上要走的就是if語句了
過來之后,在調(diào)用方法比較,比較的方法其實(shí)是與Comparatable是一樣的
📖 匿名內(nèi)部類的方式
這里并不是將Comparator這個(gè)接口實(shí)例化,而是寫成了一個(gè)匿名內(nèi)部類的形式,至于具體什么是內(nèi)部類,在之后的文章中我們將會(huì)解說。
運(yùn)行結(jié)果:
在之后,其實(shí)這里的這個(gè)內(nèi)部類可以轉(zhuǎn)化為lamada表達(dá)式,代碼會(huì)變的更簡潔,但是代碼的可閱讀性就會(huì)變的更差。
📒 覆寫基類中的equals
public class Student {public int ID;public String name;public Student(int Id,String name){this.ID = Id;//學(xué)號this.name=name;//姓名}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return ID == student.ID && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(ID, name);}@Overridepublic String toString() {return "Student{" +"ID=" + ID +", name='" + name + '\'' +'}';}} class priority{public static void main(String[] args) {Student student1 = new Student(1,"1號");Student student2 = new Student(1,"1號");System.out.println(student1.equals(student2));}}📖注意事項(xiàng):
📖缺陷:
只能按照相等與否進(jìn)行比較,不能按照大于或小于的方式進(jìn)行比較
🔓 總結(jié)
1 利用JAVA源碼去分析,可以發(fā)現(xiàn),對于非基本數(shù)據(jù)類型的對象的比較就是需要我們通過設(shè)定對應(yīng)的比較方式去進(jìn)行比較,這樣我們才可以進(jìn)行比較
2 優(yōu)先級隊(duì)列中是不能offer(null)的,這樣會(huì)拋出空異常!
3 對于Comparable接口,正如我們之前所學(xué)的那樣,擁有一個(gè)比較大的缺點(diǎn),就是對類的侵入性強(qiáng),如果我們改動(dòng)類里面的比較方式,那么就可能會(huì)導(dǎo)致代碼出現(xiàn)異常。
4 對于Comparable,我們其實(shí)可以使用比較器Comparator去實(shí)現(xiàn),從而可以減少對類的侵入性。
5 對于Comparator比較器而言,我們可以寫多個(gè)比較器,可以利用學(xué)號寫一個(gè)比較器,也可以利用姓名寫一個(gè)比較器。
總結(jié)
以上是生活随笔為你收集整理的从源码出发:JAVA中对象的比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 栈的基本应用
- 下一篇: 常见的排序算法(1)