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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Set 、HashSet、TreeSet、LinkedHashSet、EnumSet

發布時間:2025/4/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Set 、HashSet、TreeSet、LinkedHashSet、EnumSet 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Set

  • 底層原理
    java中set及其子類都是由對應的Map實現的,如HashSet由HashMap實現,TreeSet由TreeMap實現等等。
private static final Object PRESENT = new Object();public boolean add(E e) {return m.put(e, PRESENT)==null;}

從上面的代碼可以看出,TreeSet的add函數,底層是TreeMap的put(),key值是TreeSet的自己的key,而value是一個靜態常量對象present。

  • 是一個接口,主要繼承于Collections接口,所以具有Collection的一些常見的方法。
  • 因為Collections是一個抽象的接口,所以不能直接實例化一個set對象。這與Map一樣。(即Set s = new Set() 是錯誤的
  • 不能存儲相同的元素。
  • 只能有一個NULL值(TreeSet除外,TreeSet不允許有null)。
  • 常見的方法

    Sr.No.Method & Description
    1

    add( ) ? ? ? ??向集合中添加元素

    2

    clear( ) ? ? ? ?去掉集合中所有的元素

    3

    contains( ) ? ?判斷集合中是否包含某一個元素

    4

    isEmpty( ) ? ?判斷集合是否為空

    5

    iterator( ) ? ?主要用于遞歸集合,返回一個Iterator()對象

    6

    remove( ) ? ?從集合中去掉特定的對象

    7

    size( ) ? ? ? ?返回集合的大小

    HashSet

    • 底層實現:HashMap
    • 底層數據結構是:哈希表
    • 是否有序:無序:有序指的是表中存儲的位置順序和插入順序是否一致,若一致,則為有序
    • 是否排序:否
    • 是否線程安全:否
    • 能否存入重復元素:不能
    • 如何保證元素的唯一性:HashCode()與equals():首先把先加入元素的HashCode值與已有元素的進行比較,如果不同,直接add,如果相同,則使用equals()比較值是否相等,不相等,則add,相等則丟棄。
    • 能否存入空元素:能,但是只能存入一個null
    • 存儲內容:僅限對象:下面的代碼插入的也不是基本類型的,是Integer類型的,所以存儲的是對象。
    • 遍歷方式:Iterator或者for-each或者直接輸出。
      代碼為證
    public static void main(String[] args) {HashSet<Integer> hs=new HashSet<Integer>();hs.add(1);hs.add(10);hs.add(6);hs.add(12);hs.add(18);hs.add(6);Iterator<Integer> iter=hs.iterator();while(iter.hasNext()) {System.out.print(iter.next()+"--");}System.out.println();System.out.print("for-each:");for (Integer integer : hs) {System.out.print(integer+"--");}System.out.println();System.out.print(hs);}

    輸出結果:

    1--18--6--10--12-- for-each:1--18--6--10--12-- [1, 18, 6, 10, 12]

    TreeSet

    • 底層實現:TreeMap
    • 底層數據結構:紅黑樹
    • 是否排序:是
    • 是否有序:否
    • 是否線程安全:否
    • 能否存入重復元素:不能
    • 能否存入null元素:不能:插入null時會報NullPointerException
    • 如何保證元素排序:自然排序和比較器排序
    • 如何保證元素唯一:根據比較的返回值是否是0來決定
    • 遍歷方式:Iterator或者for-each或者直接輸出。
      有代碼為證:
      注意:當使用自定義的類時,需要重寫排序規則,否則會拋出一個異常:java.lang.ClassCastException,因為我們沒有指定比較規則。可參考:
      https://www.cnblogs.com/yzssoft/p/7127894.html
    public static void main(String[] args) {TreeSet<Object> ts=new TreeSet<Object>();for (Integer integer : Arrays.asList(10,12,5,13,4,6,0)) {ts.add(integer);}System.out.println("TreeSet的數字測試:");for (Object object : ts) {System.out.print(object+"--");}ts.removeAll(ts);for (String str : Arrays.asList("apple","delete","book","cook","","desk")) {ts.add(str);}System.out.println("\n"+"TreeSet的字符串測試:");System.out.println("TreeSet的當前大小為:"+ts.size());for (Object object : ts) {System.out.print(object+"--");}}

    運行結果:

    TreeSet的數字測試: 0--4--5--6--10--12--13-- TreeSet的字符串測試: TreeSet的當前大小為:6 --apple--book--cook--delete--desk--//這里""是第一個輸出的

    LinkedHashSet

    • 底層實現:使用LinkedHashMap來保存所有元素,通過計算HashCode值來確保元素的唯一性。
    • 底層數據結構:雙向鏈表
    • 是否有序:是FIFO
    • 是否排序:否
    • 是否線程安全:否
    • 能否存入重復元素:不能
    • 能否存入null:能:即使同時有多個null值存入,也不會報錯,但是輸出時只有最先存入的null值輸出(畢竟也是通過hashCode值來判斷存儲的)。
    • 遍歷方式:Iterator或者for-each或者直接輸出。
      代碼為證
    public static void main(String[] args) {LinkedHashSet<Object> lhs=new LinkedHashSet<Object>();for (Integer integer : Arrays.asList(10,12,null,12,null,5,13,4,6,0)) {lhs.add(integer);}System.out.println("LinkedHashSet的數字測試:");System.out.println("LinkedHashSet的當前大小為:"+lhs.size());for (Object object : lhs) {System.out.print(object+"--");}for (String str : Arrays.asList("apple","delete","book","cook","","desk")) {lhs.add(str);}System.out.println("\n"+"LinkedHashSet的字符串測試:");System.out.println("LinkedHashSet的當前大小為:"+lhs.size());for (Object object : lhs) {System.out.print(object+"--");}}

    運行結果:

    LinkedHashSet的數字測試: LinkedHashSet的當前大小為:8 10--12--null--5--13--4--6--0-- LinkedHashSet的字符串測試: LinkedHashSet的當前大小為:14 10--12--null--5--13--4--6--0--apple--delete--book--cook----desk--

    EnumSet

    • 底層數據結構:位運算:EnumSet在內部以位向量的形式存儲,這種存儲形式非常緊湊、高效,因此EnumSet對象占用內存很小,而且運行效率很好。尤其是進行批量操作(如調用containsAll()和retainAll()方法)時,如果其參數也是EnumSet集合,則該批量操作的執行速度也非常快。
    • EnumSet是抽象類,只能通過靜態工廠方法構造EnumSet對象:EnumSet類沒有暴露任何構造器來創建該類的實例,程序應該通過它提供的類方法來創建EnumSet對象
    • 是否允許null元素:不允許:試圖插入 null 元素將拋出 NullPointerException。但是,
      試圖測試是否出現 null 元素或移除 null 元素將不會拋出異常(而且EnumSet類中也不允許有null)
    • 是否線程安全:否
    • 能否存入重復元素:否(首先枚舉類里就不允許有重復的元素)
    • 是否有序:有序
      代碼在下
    import java.util.EnumSet;public class EnumSetDemo {public static void main(String[] args) {//1.創建一個包含number(枚舉類)里所有枚舉值的EnumSet集合EnumSet<number> es=EnumSet.allOf(number.class);System.out.println("es:"+es);//2.創建一個空EnumSet,//只能向空EnumSet中添加枚舉類中已有的元素EnumSet<number> es2=EnumSet.noneOf(number.class);es2.add(number.a3);System.out.println("es2"+es2);//3.以指定的枚舉值創建EnumSet集合EnumSet<number> es3=EnumSet.of(number.a1,number.a3);System.out.println("es3:"+es3);//4.創建一個包含枚舉類一個范圍內元素的EnumSetEnumSet<number> es4=EnumSet.range(number.a2, number.a4);System.out.println("es4:"+es4);//5.創建一個包含指定EnumSet集合元素補集的EnumSet集合EnumSet<number> es5=EnumSet.complementOf(es4);System.out.println("es5:"+es5);//6.最喜歡的copy啊EnumSet<number> es6=EnumSet.copyOf(es4);Iterator<number> iter=es6.iterator();System.out.print("es6:");while(iter.hasNext()) {System.out.print(iter.next()+"--");}}}enum number{a1,a2,a3, a4 }

    運行結果:

    es:[a1, a2, a3, a4] es2[a3] es3:[a1, a3] es4:[a2, a3, a4] es5:[a1] es6:a2--a3--a4--

    另附一篇參考TreeSet(對自定義的類如何使用TreeSet:需要重寫Hashcode和equale方法,因為TreeSet中的存放的對象必須能排序,否則會報錯。)

    package Set;import java.util.Set; import java.util.TreeSet;class Student1 implements Comparable<Student1>{int id;public Student1(int id) {this.id = id;}@Overridepublic String toString() {return this.id+"";}@Overridepublic int hashCode() {return this.id;}@Overridepublic boolean equals(Object obj) {if (obj instanceof Student1){Student1 stu = (Student1) obj;if (stu.id == this.id)return true;}return false;}public int compareTo(Student1 o) {return (this.id-o.id);} }public class Tree_Set {public static void main(String[] args) {Set<Student1> set = new TreeSet<Student1>();Student1 s1 = new Student1(5);Student1 s2 = new Student1(1);Student1 s3 = new Student1(2);Student1 s4 = new Student1(4);Student1 s5 = new Student1(3);set.add(s1);set.add(s2);set.add(s3);set.add(s4);set.add(s5);for (Student1 s : set) {System.out.println(s);}}}

    LinkedHashSet:具有HashSet的查詢速度,且內部使用鏈表維護元素的順序(插入的次序)。于是在使用迭代器遍歷Set時,結果會按照元素插入的次序顯示。

    package Set;import java.util.Iterator;public class LinkedHashSet {public static void main(String[] args) {java.util.LinkedHashSet<String> books = new java.util.LinkedHashSet<String>();books.add("Book1");books.add("Book2");books.add("Book1");System.out.println(books);//刪除 Book1books.remove("Book1");//重新添加 Book1books.add("Book1");System.out.println(books);for(Iterator<String> iter = books.iterator(); iter.hasNext();){Object value = iter.next();System.out.println(value);}} }

    運行結果:

    [Book1, Book2] [Book2, Book1] Book2 Book1

    因為LinkedHashSet是HashSet的子類,因此它不允許集合元素重復。所以第二個books.add("Book1");沒有添加進去。

    Set集合類應用場景

  • HashSet的性能總是比TreeSet好(特別是最常用的添加、查詢元素等操作),因為TreeSet需要額外的紅黑樹算法來維護集合元素的次序。只有當需要一個保持排序的Set時,才應該使用TreeSet,否則都應該使用HashSet
  • 對于普通的插入、刪除操作,LinkedHashSet比HashSet要略慢一點,這是由維護鏈表所帶來的開銷造成的。不過,因為有了鏈表的存在,遍歷LinkedHashSet會更快
  • EnumSet是所有Set實現類中性能最好的,但它只能保存同一個枚舉類的枚舉值作為集合元素
  • HashSet、TreeSet、EnumSet都是"線程不安全"的,通常可以通過Collections工具類的synchronizedSortedSet方法來"包裝"該Set集合。
    SortedSet s = Collections.synchronizedSortedSet(new TreeSet(…));
  • 總結

    以上是生活随笔為你收集整理的Set 、HashSet、TreeSet、LinkedHashSet、EnumSet的全部內容,希望文章能夠幫你解決所遇到的問題。

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