1. 程式人生 > >JAVA-初步認識-常用對象API(集合框架-treeset集合)

JAVA-初步認識-常用對象API(集合框架-treeset集合)

依據 三種 姓名 inf 健壯性 框架 第一個 註意 是不是

一.

接下來講解set中的常用子類treeset,演示一下treeset的特點。

集合講述到這裏,談論的都是不同集合內部的數據結構。

技術分享圖片

技術分享圖片

這裏必須采用叠代器輸出,輸出的結果是無序的。看到的存進去和取出來的是不一致的,但是取出來的結果有些規律,按照字符的首字母排序來輸出。

這個我們不稱之為有序,是有指定順序,按照元素的字典順序排列。

看下treeset的特點,

技術分享圖片

技術分享圖片

既然我們往裏面存了一些字符串了,輸出的時候,也按照字典的順序排列完了。下面就要存儲一些自定義對象。

技術分享圖片

技術分享圖片

結果顯示錯誤,(按照之前的寫法出錯),類型轉換異常。

第19行,wangwu出現了錯誤。如果只保留zhangsan那一行,結果沒有問題。保留兩行還是出錯,

技術分享圖片

技術分享圖片

treeset集合幹嘛的?給元素排序用的,排序就必然意味著比較。只存一個對象,不用比較。存兩個對象就要比較。

保留兩行的時候,比不了,因為這個person類沒有比較功能。有人說寫了equals,這裏需要的是比較,而不是判斷相同。比較是要分大小的,情況不是兩種,是三種的。

我們現在看一下,java.lang.Comparable到底是什麽。

技術分享圖片

讀了上面的截圖,有什麽感受?person正常描述人這類事物,該有什麽描述什麽。描述完了以後,我現在要把person放到treeset集合中進行排序。你覺得person

是不是應該在已具備的基本功能之外,要具備一個擴展功能就是比較(為什麽不是treeset集合掌握這個功能呢

?)。這個比較怎麽來呢?它本身已經被定義在congparable接口當中,如果你想讓人具備比較性,只要對人進行一個功能擴展,讓其實現comparable接口,就具備了比較功能。

人需要進行比較,因此要實現comparable(在eclipse中大小寫都可以,名字太長的可以采用out+斜線)

技術分享圖片

技術分享圖片

要先繼承後實現,不寫繼承object也行。person類中覆蓋了Comparable接口中的copareTo方法。這裏返回的是int,對象比較返回的是什麽結果?不要說成-1,那其實是負數,數字隨時可以變化的。

技術分享圖片

現在回過來看原先的例子,輸入五個元素,看下圖,結果沒有錯誤。

技術分享圖片

輸出只有一個,但是沒有報錯。我們將wangwu換到第一個添加位置,結果只輸出wangwu。先存的是wangwu,當存儲zhangsan的時候,它和wangwu一比,返回的是0,返回0意味著這兩個元素相同,而treeset集合是set集合的一個子類,它們都有一個共性特點,叫做保證元素的唯一性。

treeset和hashcode,equals有關系麽?一點關系都沒有,例子開始時,就有hashcode和equals兩個方法,輸出也是報錯,也沒行。

treeset集合根本就不看hashcode和equals,而正因為寫了一個compareto方法,並返回了0,它就視為下面的元素和wangwu相同。所以treeset集合判斷元素唯一性的方式特別簡單,就是根據.....

技術分享圖片

因為結構不一樣,和其它容器全不一樣,treeset就看比較結果,只要是0,就按相同算。

有人說,不能這麽算,得寫一些具體的,意思是說,上面解決異常的操作太粗糙了。沒有用到對象自身的一些特性,直接compareto得到0,現在想要精細一些。

把person存到treeset中,沒有說要按照什麽明確的需求排,這就是問題。

人這個類既有姓名,又有年齡,按照什麽方式排序沒有明確過,這是問題。現在,我們開始明確,以person對象的年齡按照從小到大來進行排序。也就是說我們要將這個要求寫在person的compareto方法裏。要是返回0,那麽所有元素都相同,那肯定是不行的。

我們先要轉換對象類型,有人說這裏需要進行判斷。這裏就不用了,以後會進行統一的改觀。現在先簡化地寫一下,判斷肯定是需要地。凡是類型強轉,尤其是引用數據類型之前,一定要先加健壯性判斷(instanceof),否則會發生classcast異常。下面就是將person類中的compareto方法進行復寫的結果。

技術分享圖片

技術分享圖片

按照年齡比較的結果來存儲數據到集合中。最終顯示是可以的,這是分布在兩個class文件中的代碼,treeset應該還有其它的限制條件,不僅僅是目前compareto方法中的比較年齡。

我們看輸出的結果是從小到大的,如何將其調整為從大到小。將return中的-1和1調換一下。還有另一種方法,將this和p調換一下。後期有一種對順序進行逆轉的動作,源碼中return中的-1和1,以及<和>都是很難改變的,但是this和p是引用變量,方法修改。

排完序後,對程序進行修改,將其中的兩個自定義對象的年齡設置成一樣的。

技術分享圖片

技術分享圖片

結果中zhouqi不在了,wangwu還在。原因是什麽?在compareto方法的定義中,zhouqi和wangwu的年齡既不大於,也不小於,是等於。那麽這兩個元素就是一樣的,是同一個對象,這樣zhouqi就被取消了。

有人說這個判斷少一步,當年齡判斷相同的時候,應該再判斷一次姓名。

註意,我們在寫這個比較動作的時候,我們通常依據的條件都不唯一,叫做有可能有主要條件的同時,還存在著次要條件。叫做如果主要條件相同,繼續按照次要的條件繼續進行比較。

有的條件不唯一,那就繼續寫(說的都是compareto方法體中的定義)。如果年齡排不了了,那就按照姓名排。姓名是字符串,字符串本身具備著compareto的方法,

它的這個方法也來自與comparable接口。只要對象想要進行比較,就實現這個comparable接口(統一接口)。

技術分享圖片

技術分享圖片

但是這兩種寫法不太好,換種簡單的寫法。

技術分享圖片

技術分享圖片

修改完之後,wangwu和zhouqi都出現了,並且wangwu排在前面。

上面講述的就是treeset可以對元素進行排序的操作。為什麽剛才往裏面存儲字符串就可以排序呢?因為字符串本身就實現了comparable。

技術分享圖片

技術分享圖片

技術分享圖片

JAVA-初步認識-常用對象API(集合框架-treeset集合)