Java集合框架(二)—— HashSet、LinkedHashSet、TreeSet和EnumSet
-
Set接口
前面已經簡紹過Set集合,它類似于一個罐子,一旦把對象'丟進'Set集合,集合里多個對象之間沒有明顯的順序。Set集合與Collection基本上完全一樣,它沒有提供任何額外的方法。
Set集合不容許包含相同的元素,如果試圖把兩個相同元素加入到同一個Set集合中,則添加操作失敗,add方法返回false,且新元素不會被加入。
Set判斷兩個對象是否相同不是使用==運算符,而是根據equals方法。也就是說,只要兩個對象用equals方法比較返回true,Set就不會接受這兩個對象,反之,只要兩個對象用equals方法比較返回false,Set就會接受這兩個對象(甚至這兩個對象是同一個對象,Set也可把他們當成倆個對象處理),下面是Set的使用案例。
public class Test {public static void main(String[] args){Set set = new HashSet();boolean a = set.add(new String("語文"));boolean b = set.add(new String("語文"));//打印結果為true System.out.println(a);//打印結果為false System.out.println(b);/** 打印結果為[語文];* 因為兩個字符串通過equals方法比較返回為true(String類默認重寫了Object中equals方法),所以第二次添加失敗 */System.out.println(set);} }? 從上面程序中可以看出,books集合兩次添加的字符串對象明顯不是同一個對象(因為兩次都調用了new關鍵字來創造字符串對象),這兩個字符串對象使用==運算符判斷肯定返回false,但它們通過equals方法比較將返回true,所以添加失敗。最后輸出set集合時,將看到輸出結果只有一個元素。
上面介紹的是Set集合的通用知識,完全適合HashSet、TreeSet和EnumSet三個實現類。
-
HashSet類
HashSet具有以下特點:
HashSet還有一個子類LinkedHashSet,LinkedHashSet集合也是根據元素hashCode值來決定元素存儲位置,但它同時使用鏈表維護元素的次序,這樣使的元素看起來是以插入的順序保存的。也就是說當遍歷LinkedHashSet集合里的元素時,HashSet將會按元素的添加順序來訪問集合里的元素。
LinkedHashSet需要維護元素的插入順序,因此性能略低于HashSet的性能,但是在迭代訪問Set里的全部元素時,將有很好的性能,因為它以列表來維護內部順序。
public class Test {public static void main(String[] args){LinkedHashSet books = new LinkedHashSet();books.add("語文");books.add("數學");books.add("英語");//刪除語文books.remove("語文");//重新添加books.add("語文");//打印結果為[數學, 英語, 語文] System.out.println(books);} }上面的集合里,元素的順序正好與添加順序一致。
-
TreeSet類
TreeSet是SortedSet接口的唯一實現(SortedSet接口繼承Set接口),正如SortedSet名字所暗示的,TreeSet可以確保集合元素處于排序狀態。與前面的HashSet集合相比,TreeSet還提供了如下幾個額外方法:
? 根據上面程序的運行結果可看出,TreeSet并不是根據元素的插入順序進行排序,而是根據元素實際值來進行排序的。
與HashSet集合采用的hash算法來決定元素的存儲位置不同,TreeSet采用紅黑樹的數據結構對元素進行排序。那么TreeSet進行排序是怎么樣的呢?TreeSet支持兩種排序方法:自然排序和定制排序。默認情況下,TreeSet采用自然排序。
-
自然排序
Java提供了一個Comparable接口,該接口里定義了一個compareTo(Object obj)方法,該方法返回一個整數值,實現該接口的類必須實現該方法,實現了該接口的類的對象就可以比較大小了。當一個對象調用該方法與另一個對象進行比較,例如obj1.compareTo(obj2); 如果該方法返回0,則表明這兩個對象相等;如果該方法返回一個正整數,則表明obj1大于obj2;如果該方法返回一個負整數,則表明obj1小于obj2。
Java的一些常用類已經實現了Comparable接口,并提供了比較大小的標準, 下面是實現了Comparable接口的常用類:
如圖所示:Integer類實現了Comparable接口:
由于上邊的Integer類實現了Comparable接口,故TreeSet會調用集合元素的compareTo(Object o)方法來比較元素之間的大小關系,然后將集合元素按升序排列(數據從低到高排列),這種方式就是自然排序。如果試圖把一個對象添加進TreeSet時,則該對象的類必須實現Comparable接口,否則程序將會拋出ClassCastException異常。代碼如下:
class Person{} public class Test {public static void main(String[] args){TreeSet<Person> persons = new TreeSet<Person>();persons.add(new Person()); System.out.println(persons); } }?以上代碼將會拋出:
-
?定制排序
TreeSet的自然排序是根據集合元素的大小,TreeSet將它們以升序排列。如果需要完成定制排序,例如以降序排列,則可以使用Comparator接口的幫助。該接口里包含了一個int compare(T o1, T o2)方法,該方法用于比較o1、o2的大小:如果該方法返回正整數,則表明o1大于o2;如果該方法返回0,則表明o1等于o2;如果該方法返回負整數,則表明o1小于o2。
如下所示:如果需要實現定制排序(我們這實現倒序),則需要在創建TreeSet集合對象時,并提供一個Comparator對象與該TreeSet集合關聯,由該Comparator對象負責集合元素的排序邏輯。
class Person{Integer age;public Person(int age){this.age = age;}@Overridepublic String toString() {return "Person [age=" + age + "]";} } public class Test {public static void main(String[] args){TreeSet<Person> persons = new TreeSet<Person>(new Comparator<Person>(){@Overridepublic int compare(Person o1, Person o2) {if(o1.age > o2.age){return -1;}else if(o1.age == o2.age){return 0;}else{return 1;}}});persons.add(new Person(2));persons.add(new Person(5));persons.add(new Person(6));//打印結果為[Person [age=6], Person [age=5], Person [age=2]]倒序 System.out.println(persons);} }? 上面程序創建了一個Compartor接口的匿名內部類對象,該對象負責persons集合的排序。所以當我們把Person對象添加到persons集合中時,無須Person類實現Comparable接口,因為此時TreeSet無須通過Person對象來比較大小,而是由與TreeSet關聯的Compartor對象來負責集合元素的排序。
-
EnumSet類
EnumSet是一個專為枚舉設計的集合類,EnumSet中所有值都必須是指定枚舉類型的枚舉值,該枚舉類型在創建EnumSet時顯式或隱性的指定。EnumSet的集合元素也是有序的,EnumSet以枚舉值在Enum類內的定義順序來決定集合元素的排序。
EnumSet在內部以位向量的形式存儲,這種存儲形式非常緊湊、高效,因此EnumSet對象占用內存很小,而且運行效率很好。尤其是當進行批量操作(如調用containsAll和retainAll方法)時,如其參數也是EnumSet集合,則該批量操作的執行速度也非常快。
EnumSet集合不容許加入null元素。如果試圖插入null元素,EnumSet將會拋出NullPointerException異常。
EnumSet類沒有暴露任何構造器來創建該類的實例,程序應該通過它提供的static方法來創建EnumSet對象。它提供了如下常用static方法來創建EnumSet對象:
-
總結
轉載于:https://www.cnblogs.com/guoyaohua/p/8437098.html
總結
以上是生活随笔為你收集整理的Java集合框架(二)—— HashSet、LinkedHashSet、TreeSet和EnumSet的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RIP应用实验:
- 下一篇: 树莓派 更新 时间 时区