日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java集合框架(二)—— HashSet、LinkedHashSet、TreeSet和EnumSet

發布時間:2025/4/16 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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具有很好的對象檢索性能,當從HashSet中查找某個對象時,Java系統首先調用對象的hashCode方法獲得該對象的哈希碼,然后根據哈希碼找到對應的存儲區域,最后取出該存儲區域的每個元素與該對象進行equals方法的比較,這樣不用遍歷集合中的所有元素就可以得到結論。
  • HashSet存儲對象的效率相對要低些,因為向HashSet集合中添加對象的時候,首先要計算出來對象的哈希碼和根據這個哈希碼來確定對象在集合中的存放位置。
  • 不能保證排列的順序,順序有可能發生改變。
  • HashSet不是同步的(非同步,非線程安全,如果多個線程同時訪問一個HashSet集合,如果有2條或者2條以上線程同時修改了HashSet集合時,必須通過代碼來保證其同步。
  • HashSet集合元素可以是null
  •   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還提供了如下幾個額外方法:

  • Comparator comparator(); //返回當前Set使用的Comparator,或者返回null,表示以自然方式排序。
  • Object first();?? //第一個;返回集合中的第一個元素。
  • Object last();?? //最后一個;返回集合中的最后一個元素。
  • Object lower(Object o);??? //前一個;返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,參考元素不需要是TreeSet的元素)。?
  • Object higher(Object o);? //后一個;返回集合中位于指定元素之后的元素(即大于指定元素的最小元素,參考元素不需要是TreeSet的元素)。
  • SortedSet subSet(fromElement, toElement);??? //返回此Set的子集合,范圍從fromElement(包含)到toElement(不包含)。
  • SortedSet headSet(toElement);  //返回此set的子集,由小于toElement的元素組成。
  • SortedSet tailSet(fromElement);??? //返回此set的子集,由大于或等于fromElement的元素組成。
  • public class Test {public static void main(String[] args){TreeSet<Integer> nums = new TreeSet<Integer>();nums.add(3);nums.add(1);nums.add(5);nums.add(-9);//1.返回第一個元素Integer first = nums.first();//打印結果為-9 System.out.println(first);//2.返回最后一個元素Integer last = nums.last();//打印結果為5 System.out.println(last);//3.返回上一個Integer lower = nums.lower(2);//打印結果為1 System.out.println(lower);//4.返回下一個Integer higher = nums.higher(2);//打印結果為3 System.out.println(higher);//5.返回小于3的子集,不包含3SortedSet<Integer> headSet = nums.headSet(3);//打印結果[-9, 1] System.out.println(headSet);//6.返回大于等于3的子集,包含3SortedSet<Integer> tailSet = nums.tailSet(3);//打印結果[3, 5] System.out.println(tailSet);//7.打印整個集合結果為[-9, 1, 3, 5] System.out.println(nums);} }

    ?  根據上面程序的運行結果可看出,TreeSet并不是根據元素的插入順序進行排序,而是根據元素實際值來進行排序的。

      與HashSet集合采用的hash算法來決定元素的存儲位置不同,TreeSet采用紅黑樹的數據結構對元素進行排序。那么TreeSet進行排序是怎么樣的呢?TreeSet支持兩種排序方法:自然排序和定制排序。默認情況下,TreeSet采用自然排序。

    • 自然排序

      Java提供了一個Comparable接口,該接口里定義了一個compareTo(Object obj)方法,該方法返回一個整數值,實現該接口的類必須實現該方法,實現了該接口的類的對象就可以比較大小了。當一個對象調用該方法與另一個對象進行比較,例如obj1.compareTo(obj2); 如果該方法返回0,則表明這兩個對象相等;如果該方法返回一個正整數,則表明obj1大于obj2;如果該方法返回一個負整數,則表明obj1小于obj2。

      Java的一些常用類已經實現了Comparable接口,并提供了比較大小的標準, 下面是實現了Comparable接口的常用類:

  • BigDecimal、BigInteger以及所有數值型對應包裝類:按它們對象的數值大小進行比較。
  • Character?:按字符的Unicode值進行比較。
  • Boolean?: true對應的包裝類實例大于false對應的包裝類實例。
  • String?: 按字符串中字符的Unicode值進行比較。
  • Date、Time?: 后面的時間、日期比前面的日期時間大。
  • 如圖所示: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對象:

  • static EnumSet allOf(Class elementType);?? 創建一個包含指定枚舉類里所有枚舉值的EnumSet集合。
  • static EnumSet complementOf(EnumSet s); 創建一個其元素類型與指定EnumSet里元素類型相同的EnumSet,新EnumSet集合包含原EnumSet所不包含的、此枚舉類剩下的枚舉值(有點繞,看下面的例子,一看就懂)。
  • static EnumSet copyOf(Collection c);? 使用一個普通集合來創建EnumSet集合。
  • static EnumSet copyOf(EnumSet s);?? 創建一個與指定EnumSet具有相同元素集合類型、相同集合元素的EnumSet。
  • static EnumSet noneOf(Class elementType); 創建一個集合類型為指定枚舉類型的空EnumSet。
  • static EnumSet of(E first, E...rest);? 創建一個包含一個或多個枚舉值的EnumSet,傳入的多個枚舉值必須屬于同一個枚舉類。
  • static EnumSet range(E first, E to);? 創建包含從from枚舉值,到to枚舉值范圍內所有枚舉值的EnumSet集合。
  • enum Season{SPRING,SUMMER,AUTUMN,WINTER } public class Test {public static void main(String[] args){//1.0創建一個EnumSet集合,集合元素就是Season枚舉類的全部枚舉值EnumSet<Season> es = EnumSet.allOf(Season.class);System.out.println(es);//輸出[SPRING, SUMMER, AUTUMN, WINTER]//2.0創建一個EnumSet空集合,指定其集合元素時Season類的枚舉值。EnumSet<Season> es2 = EnumSet.noneOf(Season.class);System.out.println(es2);//輸出[]//2.1手動添加兩個元素 es2.add(Season.AUTUMN);es2.add(Season.WINTER);System.out.println(es2);//輸出[AUTUMN, WINTER]//3.0以指定枚舉值創建EnumSet集合EnumSet<Season> es3 = EnumSet.of(Season.SPRING, Season.SUMMER);System.out.println(es3);//輸出[SPRING, SUMMER]//4.0創建包含從Season.SPRING枚舉值,到Season.AUTUMN枚舉值范圍內所有枚舉值的EnumSet集合。EnumSet<Season> es4 = EnumSet.range(Season.SPRING, Season.AUTUMN);System.out.println(es4); //輸出[SPRING, SUMMER, AUTUMN]//5.0新創建的EnumSet集合元素和es4集合的元素有相同類型,es5的集合元素 + es4的集合元素 = Season 的所有枚舉值EnumSet<Season> es5 = EnumSet.complementOf(es4);System.out.println(es5); //輸出[WINNER]//6.0復制Collection集合中所有元素來創建EnumSet集合。Collection<Season> c = new HashSet<Season>();c.add(Season.AUTUMN);c.add(Season.WINTER);EnumSet<Season> es6 = EnumSet.copyOf(c);System.out.println(es6); //輸出[AUTUMN, WINTER] } }
    • 總結

  • HashSet和TreeSet是Set的兩個典型實現,HashSet的性能總是比TreeSet好(特別是比較常用的添加、查詢元素等操作),因為TreeSet需要額外的紅黑樹算法來維護集合元素的次序。只有當需要一個保持排序的Set時,才應該使用TreeSet,否則都應該使用HashSet。
  • HashSet還有一個子類:LinkedHashSet,對于普通插入、刪除操作,LinkedHashSet比HashSet要略微慢一點;這是由維護鏈表所帶來的額外開銷所造成的,不過,因為有了鏈表,遍歷LinkedHashSet會更快
  • EnumSet是所有Set實現類中性能最好的,但它只能保存同一個枚舉類的枚舉值做為集合元素。
  • Set的三個實現類HashSet(包括LinkedHashSet)、TreeSet和EnumSet都是線程不安全的。如果有多個線程同時訪問一個Set集合,并且有超過一條線程修改了該Set集合,則必須手動保證該Set集合的同步性。通常可以通過Collections工具類的synchronizedSet方法來"包裝"該Set集合。此操作最好在創建時進行,以防止對Set集合的意外非同步訪問。例如:Set hs = Collections.synchronizedSet(new HashSet());
  • 轉載于:https://www.cnblogs.com/guoyaohua/p/8437098.html

    總結

    以上是生活随笔為你收集整理的Java集合框架(二)—— HashSet、LinkedHashSet、TreeSet和EnumSet的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 69视频免费观看 | 日日爱影视 | 中文字幕精品久久久久人妻红杏1 | 97se综合 | 国产成人高清在线 | 织田真子作品 | 无码人妻精品一区二区三区夜夜嗨 | 9999热视频 | 国产成人精品无码片区在线 | 久久精品99久久久久久久久 | 日本va欧美va欧美va精品 | 亚洲av成人精品日韩在线播放 | 成人性做爰aaa片免费 | 91叉叉叉| 91精品91 | 91污片 | 羞羞漫画在线播放 | 四虎色网 | 视频一区二区免费 | 男人天堂1024| 国产小视频网址 | 日日爱网站 | 日韩中出 | 国产福利视频导航 | 外国av网站| 久久丫丫 | 欧美日韩精品中文字幕 | 超碰免费观看 | 国产成人精 | 亚洲国产一区二区三区在线观看 | 色呦呦日韩精品 | 婷婷中文在线 | 久久精品免费观看 | 91成人免费在线 | 九月激情网 | 国产日韩久久 | 久久精品视频中文字幕 | 精品成人国产 | 亚洲av成人精品毛片 | 欧美综合色 | 成人免费小视频 | 亚洲熟妇av一区二区三区 | 欧美贵妇videos办公室 | 91福利网站 | 亚洲国产成人一区 | 久久加久久 | 四色网址| 国产综合社区 | 黄色大片久久 | 欧美黄色性视频 | 亚洲黄色激情 | 在线观看成年人网站 | 天堂网久久 | 奇米影视中文字幕 | 黄色一级视频片 | 姝姝窝人体www聚色窝 | 日韩精品成人无码专区免费 | 91久久精品美女高潮 | 影音先锋中文字幕一区二区 | 欧美乱码精品 | 欧美色图在线视频 | 国产老熟女伦老熟妇露脸 | 四虎影院在线观看免费 | 国产区亚洲区 | 日本在线不卡一区 | 6080午夜| 国产一线二线三线在线观看 | 亚洲影视一区二区三区 | 免费在线观看中文字幕 | 捆绑中国女人hd视频 | 免费啪视频在线观看 | 人人狠狠 | 在线观看国产一区二区 | 51精品国产人成在线观看 | 91高清无打码 | 小视频在线看 | 华人在线视频 | 国产一区中文 | 一级特黄性色生活片 | 国产午夜性春猛交ⅹxxx | 色婷婷yy | 国产精品精品久久久 | 免费av网页 | 又黄又爽视频 | 婷婷av在线| 97在线影院 | 九九国产 | 最近中文字幕在线视频 | 国产视频1区2区3区 国产欧美一区二区精品性色99 | 日本55丰满熟妇厨房伦 | 日皮视频免费看 | 国产精品自拍电影 | 嫩草av久久伊人妇女超级a | 成人字幕| 欧美xxxx少妇| 日日射夜夜操 | www.黄色. | 久操亚洲 | 国产黄色免费 |