日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Set 、HashSet、TreeSet、LinkedHashSet、EnumSet

發(fā)布時(shí)間:2025/4/16 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Set 、HashSet、TreeSet、LinkedHashSet、EnumSet 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Set

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

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

  • 是一個(gè)接口,主要繼承于Collections接口,所以具有Collection的一些常見的方法。
  • 因?yàn)镃ollections是一個(gè)抽象的接口,所以不能直接實(shí)例化一個(gè)set對(duì)象。這與Map一樣。(即Set s = new Set() 是錯(cuò)誤的
  • 不能存儲(chǔ)相同的元素。
  • 只能有一個(gè)NULL值(TreeSet除外,TreeSet不允許有null)。
  • 常見的方法

    Sr.No.Method & Description
    1

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

    2

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

    3

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

    4

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

    5

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

    6

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

    7

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

    HashSet

    • 底層實(shí)現(xiàn):HashMap
    • 底層數(shù)據(jù)結(jié)構(gòu)是:哈希表
    • 是否有序:無序:有序指的是表中存儲(chǔ)的位置順序和插入順序是否一致,若一致,則為有序
    • 是否排序:否
    • 是否線程安全:否
    • 能否存入重復(fù)元素:不能
    • 如何保證元素的唯一性:HashCode()與equals():首先把先加入元素的HashCode值與已有元素的進(jìn)行比較,如果不同,直接add,如果相同,則使用equals()比較值是否相等,不相等,則add,相等則丟棄。
    • 能否存入空元素:能,但是只能存入一個(gè)null
    • 存儲(chǔ)內(nèi)容:僅限對(duì)象:下面的代碼插入的也不是基本類型的,是Integer類型的,所以存儲(chǔ)的是對(duì)象。
    • 遍歷方式: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);}

    輸出結(jié)果:

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

    TreeSet

    • 底層實(shí)現(xiàn):TreeMap
    • 底層數(shù)據(jù)結(jié)構(gòu):紅黑樹
    • 是否排序:是
    • 是否有序:否
    • 是否線程安全:否
    • 能否存入重復(fù)元素:不能
    • 能否存入null元素:不能:插入null時(shí)會(huì)報(bào)NullPointerException
    • 如何保證元素排序:自然排序和比較器排序
    • 如何保證元素唯一:根據(jù)比較的返回值是否是0來決定
    • 遍歷方式:Iterator或者for-each或者直接輸出。
      有代碼為證:
      注意:當(dāng)使用自定義的類時(shí),需要重寫排序規(guī)則,否則會(huì)拋出一個(gè)異常:java.lang.ClassCastException,因?yàn)槲覀儧]有指定比較規(guī)則。可參考:
      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的數(shù)字測(cè)試:");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的字符串測(cè)試:");System.out.println("TreeSet的當(dāng)前大小為:"+ts.size());for (Object object : ts) {System.out.print(object+"--");}}

    運(yùn)行結(jié)果:

    TreeSet的數(shù)字測(cè)試: 0--4--5--6--10--12--13-- TreeSet的字符串測(cè)試: TreeSet的當(dāng)前大小為:6 --apple--book--cook--delete--desk--//這里""是第一個(gè)輸出的

    LinkedHashSet

    • 底層實(shí)現(xiàn):使用LinkedHashMap來保存所有元素,通過計(jì)算HashCode值來確保元素的唯一性。
    • 底層數(shù)據(jù)結(jié)構(gòu):雙向鏈表
    • 是否有序:是FIFO
    • 是否排序:否
    • 是否線程安全:否
    • 能否存入重復(fù)元素:不能
    • 能否存入null:能:即使同時(shí)有多個(gè)null值存入,也不會(huì)報(bào)錯(cuò),但是輸出時(shí)只有最先存入的null值輸出(畢竟也是通過hashCode值來判斷存儲(chǔ)的)。
    • 遍歷方式: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的數(shù)字測(cè)試:");System.out.println("LinkedHashSet的當(dāng)前大小為:"+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的字符串測(cè)試:");System.out.println("LinkedHashSet的當(dāng)前大小為:"+lhs.size());for (Object object : lhs) {System.out.print(object+"--");}}

    運(yùn)行結(jié)果:

    LinkedHashSet的數(shù)字測(cè)試: LinkedHashSet的當(dāng)前大小為:8 10--12--null--5--13--4--6--0-- LinkedHashSet的字符串測(cè)試: LinkedHashSet的當(dāng)前大小為:14 10--12--null--5--13--4--6--0--apple--delete--book--cook----desk--

    EnumSet

    • 底層數(shù)據(jù)結(jié)構(gòu):位運(yùn)算:EnumSet在內(nèi)部以位向量的形式存儲(chǔ),這種存儲(chǔ)形式非常緊湊、高效,因此EnumSet對(duì)象占用內(nèi)存很小,而且運(yùn)行效率很好。尤其是進(jìn)行批量操作(如調(diào)用containsAll()和retainAll()方法)時(shí),如果其參數(shù)也是EnumSet集合,則該批量操作的執(zhí)行速度也非常快。
    • EnumSet是抽象類,只能通過靜態(tài)工廠方法構(gòu)造EnumSet對(duì)象:EnumSet類沒有暴露任何構(gòu)造器來創(chuàng)建該類的實(shí)例,程序應(yīng)該通過它提供的類方法來創(chuàng)建EnumSet對(duì)象
    • 是否允許null元素:不允許:試圖插入 null 元素將拋出 NullPointerException。但是,
      試圖測(cè)試是否出現(xiàn) null 元素或移除 null 元素將不會(huì)拋出異常(而且EnumSet類中也不允許有null)
    • 是否線程安全:否
    • 能否存入重復(fù)元素:否(首先枚舉類里就不允許有重復(fù)的元素)
    • 是否有序:有序
      代碼在下
    import java.util.EnumSet;public class EnumSetDemo {public static void main(String[] args) {//1.創(chuàng)建一個(gè)包含number(枚舉類)里所有枚舉值的EnumSet集合EnumSet<number> es=EnumSet.allOf(number.class);System.out.println("es:"+es);//2.創(chuàng)建一個(gè)空EnumSet,//只能向空EnumSet中添加枚舉類中已有的元素EnumSet<number> es2=EnumSet.noneOf(number.class);es2.add(number.a3);System.out.println("es2"+es2);//3.以指定的枚舉值創(chuàng)建EnumSet集合EnumSet<number> es3=EnumSet.of(number.a1,number.a3);System.out.println("es3:"+es3);//4.創(chuàng)建一個(gè)包含枚舉類一個(gè)范圍內(nèi)元素的EnumSetEnumSet<number> es4=EnumSet.range(number.a2, number.a4);System.out.println("es4:"+es4);//5.創(chuàng)建一個(gè)包含指定EnumSet集合元素補(bǔ)集的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 }

    運(yùn)行結(jié)果:

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

    另附一篇參考TreeSet(對(duì)自定義的類如何使用TreeSet:需要重寫Hashcode和equale方法,因?yàn)門reeSet中的存放的對(duì)象必須能排序,否則會(huì)報(bào)錯(cuò)。)

    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的查詢速度,且內(nèi)部使用鏈表維護(hù)元素的順序(插入的次序)。于是在使用迭代器遍歷Set時(shí),結(jié)果會(huì)按照元素插入的次序顯示。

    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);}} }

    運(yùn)行結(jié)果:

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

    因?yàn)長(zhǎng)inkedHashSet是HashSet的子類,因此它不允許集合元素重復(fù)。所以第二個(gè)books.add("Book1");沒有添加進(jìn)去。

    Set集合類應(yīng)用場(chǎng)景

  • HashSet的性能總是比TreeSet好(特別是最常用的添加、查詢?cè)氐炔僮?,因?yàn)門reeSet需要額外的紅黑樹算法來維護(hù)集合元素的次序。只有當(dāng)需要一個(gè)保持排序的Set時(shí),才應(yīng)該使用TreeSet,否則都應(yīng)該使用HashSet
  • 對(duì)于普通的插入、刪除操作,LinkedHashSet比HashSet要略慢一點(diǎn),這是由維護(hù)鏈表所帶來的開銷造成的。不過,因?yàn)橛辛随湵淼拇嬖?#xff0c;遍歷LinkedHashSet會(huì)更快
  • EnumSet是所有Set實(shí)現(xiàn)類中性能最好的,但它只能保存同一個(gè)枚舉類的枚舉值作為集合元素
  • HashSet、TreeSet、EnumSet都是"線程不安全"的,通常可以通過Collections工具類的synchronizedSortedSet方法來"包裝"該Set集合。
    SortedSet s = Collections.synchronizedSortedSet(new TreeSet(…));
  • 總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。