成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

java集合-Set

xavier / 2561人閱讀

摘要:集合判斷兩個元素的標(biāo)準(zhǔn)是兩個對象通過方法比較相等,并且兩個對象的方法返回值也相等。的集合元素也是有序的,以枚舉值在類內(nèi)的定義順序來決定集合元素的順序。是所有實現(xiàn)類中性能最好的,但它只能保存同一個枚舉類的枚舉值作為集合元素。

Set集合通常不能記住元素的添加順序。Set不允許包含重復(fù)的元素。

Set集合不允許包含相同的元素,如果試圖把兩個相同的元素加入同一個Set集合中,則添加操作失敗,add()方法返回false,且新元素不會被加入。

HashSet類

HashSet按照Hash算法來存儲集合中的元素,因此具有很好的存取和查詢性能。

HashSet特點

不能保證元素的排列順序,順序可能與添加順序不同,順序也有可能發(fā)生變化。

HashSet不是同步的,如果多個線程同時訪問一個HashSet,假設(shè)有兩個或者兩個以上線程同時修改了HashSet集合時,則必須通過代碼來保證其同步。

集合元素值可以是null;

當(dāng)HashSet集合中存入一個元素時,HashSet會調(diào)用該對象的HashCode()方法來得到該對象的hashCode值,然后根據(jù)該hashCode值決定該對象在HashSet中的存儲位置,如果有兩個元素通過equals()方法比較返回true,但他們的hashCode()方法返回值不相等,HashSet將會把他們存在不同位置,依然可以添加成功。

HashSet集合判斷兩個元素的標(biāo)準(zhǔn)是兩個對象通過equals()方法比較相等,并且兩個對象的hashCode()方法返回值也相等。

即使兩個A對象通過equals()方法比較返回true,但HashSet依然把他們當(dāng)成兩個對象,即使兩個B對象的hashCode()方法返回相同值,但HashSet依然把他們當(dāng)成兩個對象。

當(dāng)把一個對象放入HashSet中時,如果需要重寫該對象對應(yīng)類的equals()方法,則也應(yīng)該重寫其hashCode()方法,規(guī)則是:如果兩個對象通過equals()方法比較返回true,這兩個對象的hashCode值也應(yīng)該相同。

如果兩個對象通過equals()比較返回true,但這兩個對象的hashCode()方法返回不同的hashCode值時,這將導(dǎo)致HashSet會把這兩個對象保存在Hash表的不同位置,從而使兩個對象都可以添加成功,這就與Set集合規(guī)則沖突了。

如果兩個對象的hashCode()值返回的值相同,但他們通過equals()方法比較返回false時更麻煩。因為兩個對象的hashCode值相同,HashSet將試圖把他們保存在同一個位置,但又不行(否則將只剩下一個對象),所以實際上回在這個位置用鏈?zhǔn)浇Y(jié)構(gòu)來保存多個對象;而HashSet訪問集合元素時也是根據(jù)元素的hashCode值來快速定位的,如果HashSet中兩個以上的元素具有相同的hashCode值,將會導(dǎo)致性能下降。

Hash算法可以直接根據(jù)該元素的hashCode值計算出該元素的存儲位置,從而快速定位該元素。

數(shù)組是所有能存儲一組元素里最快的數(shù)據(jù)結(jié)構(gòu)。

當(dāng)從HashSet中訪問元素時,HashSet先計算該元素的hashCode值,也就是調(diào)用該元素的hashCode()方法的返回值,然后直接到該hashCode值對應(yīng)的位置去取出該元素。這就是HashSet速度很快的原因。

HashSet中每個能存儲元素的“槽位slot”通常稱為桶bucket,如果有多個元素的hashCode值相同,但他們通過equals方法比較返回false,就需要在一個桶里存放多個元素,就會導(dǎo)致性能下降。

重寫hashCode方法的基本原則。

在程序運行過程中,同一個對象多次調(diào)用hashCode()方法應(yīng)該返回相同的值。

當(dāng)兩個對象通過equals()方法比較返回true時,hashCode()應(yīng)該也返回相同值。

對象中用作equals()方法比較標(biāo)準(zhǔn)的實例變量,都應(yīng)該用于計算hashCode值。

當(dāng)程序把可變對象添加到HashSet中之后,盡量不要去修改該集合元素中參與計算hashCode()’equals()的實例變量,否則將會導(dǎo)致HashSet無法爭取操作這些集合。

LinkedHashSet類

LinkedHashSet集合也是根據(jù)元素的hashCode值來決定元素的存儲位置,但它同時使用鏈表維護元素的次序,LinkedHashSet將會按元素的添加順序來訪問集合里的元素。

同樣不能允許集合元素重復(fù),

public class LinkedHashSetTest {
    public static void main(String[] args) {
        Collection collection = new LinkedHashSet<>();
        collection.add("java");
        collection.add("python");
        //[java, python]
        System.out.println(collection);
        collection.remove("java");
        collection.add("java");
        //[python, java]
        System.out.println(collection);
    }
}
TreeSet類

TreeSet是StortedSet接口的實現(xiàn)類。TreeSet可以保證集合元素處于排序狀態(tài)。

public class TreeSetTest {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet<>();
        treeSet.add("5");
        treeSet.add("4");
        treeSet.add("3");
        treeSet.add("2");
        treeSet.add("1");
        System.out.println(treeSet);
        System.out.println(treeSet.first());//1
        System.out.println(treeSet.last());//5
        //返回集合中位于指定元素之前的元素
        System.out.println(treeSet.lower("4"));//3
        //返回集合中位于指定元素之后的元素
        System.out.println(treeSet.higher("4"));//5
        //返回此set的子集,由小于指定元素的元素組成
        SortedSet headSet = treeSet.headSet("4");
        System.out.println(headSet);//[1, 2, 3]
        //返回set的子集。由大于或者等于指定元素的元素組成
        SortedSet tailSet = treeSet.tailSet("4");
        System.out.println(tailSet);//[4, 5]
    }
}

Tree并不是根據(jù)元素的插入順序進(jìn)行排序的,而是根據(jù)元素實際的大小來進(jìn)行排序的。

與HashSet集合采用hash算法來決定元素的存儲位置不同,TreeSet是采用紅黑樹的數(shù)據(jù)結(jié)構(gòu)來存儲集合元素,TreeSet支持兩種排序方法,自然排序和定制排序。默認(rèn)下TreeSet采用自然排序。

自然排序

TreeSet會調(diào)用集合元素的compareTo(Object o)方法來比較元素之間的大小關(guān)系,然后將集合元素按升序排序,這種方式就是自然排序。

如果試圖把一個對象添加到TreeSet時,則該對象的類必須實現(xiàn)comparable接口。否則報錯

public class TreeSetErrorTest {
    public static void main(String[] args) {
        USER user = new USER("", 2);
        TreeSet treeSet = new TreeSet<>();
        //Exception in thread "main" java.lang.ClassCastException: setTest.USER cannot be cast to java.base/java.lang.Comparable
        treeSet.add(user);
    }
}

當(dāng)試圖把一個對象添加到TreeSet集合時,TreeSet會調(diào)用該對象的comparaTo(Object o)方法與集合中的其他元素進(jìn)行比較,這就要求集合中的其他元素與該元素時同一類的實例,也就是說,向TreeSet中添加的應(yīng)該是同一個類的對象,否則也會引發(fā)ClassCastException異常。

public class TreeSetErrorTest2 {
    public static void main(String[] args) {
        TreeSet set = new TreeSet<>();
        set.add(new String());
        //Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.util.Date
        set.add(new Date());
        /*
         * 在添加String時,是沒有錯誤的,當(dāng)添加Date對象時,TreeSet就會調(diào)用該對象的comparaTo方法與集合中的其他元素進(jìn)行比較--
         * Date對象的comparaTo方法無法與字符串對象比較大小,所以引發(fā)異常
         * */
    }
}

TreeSet只能添加同一種類型的對象,

當(dāng)把一個對象加入TreeSet集合中時,TreeSet調(diào)用該對象的compareTo(Obejct o)方法與容器中的其他對象比較大小,然后根據(jù)紅黑樹結(jié)構(gòu)找到他的存儲位置,如果兩個對象通過compareTo(Object o)方法比較相等,新對象將無法添加到TreeSet集合中。

TreeSet集合判斷兩個對象是夠相等的唯一標(biāo)準(zhǔn)是:如果通過compareTo方法比較返回0,TreeSet則會認(rèn)為他們相等,否則就認(rèn)為他們不相等。

當(dāng)需要把一個對象放入TreeSet中,重寫該對象對應(yīng)類的equals方法時,應(yīng)保證該方法與compareTo方法有一致的結(jié)果,其規(guī)則是,如果兩個對象通過equals方法比較返回true時,這兩個對象通過compareTo方法比較應(yīng)返回0;

TreeSet可以刪除沒有被修改實例變量,且不與其他被修改實例變量的對象重復(fù)的對象。P309

推薦不要修改放入HashSet和TreeSet集合中元素的關(guān)鍵實例變量。

定制排序
public class MSort {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet<>((o1,o2)->{
            M m1 = o1;
            M m2 = o2;
            return Integer.compare(m1.a, m2.a);
        });
        treeSet.add(new M(12));
        treeSet.add(new M(1232));
        treeSet.add(new M(121));
        //[12, 121, 1232]
        System.out.println(treeSet);
    }
}

當(dāng)通過Comparator對象或Lambda表達(dá)式來實現(xiàn)TreeSet的定制排序時,依然不可以向TreeSet中添加類型不同的對象,否則會引發(fā)ClassCastException異常,使用定制排序時,TreeSet對集合元素排序不管集合元素本身的大小,而是由Comparator對象或Lambda表達(dá)式。負(fù)責(zé)集合元素的排序規(guī)則,TreeSet判斷兩個集合元素相等的標(biāo)準(zhǔn)是:通過Comparator比較兩個元素返回了0,這樣TreeSet不會把第二個元素添加到集合中。

EnumSet類

EnumSet是一個轉(zhuǎn)為枚舉類設(shè)計的集合類,EnumSet中的所有元素都必須是指定枚舉類型的枚舉值,該枚舉值在創(chuàng)建EnumSet時顯示或隱式地指定。EnumSet的集合元素也是有序的,EnumSet以枚舉值在Enum類內(nèi)的定義順序來決定集合元素的順序。

EnumSet在內(nèi)部以位向量的形式存儲,這種存儲形式非常緊湊高效,因此EnumSet對象占用內(nèi)存很小,運行效率好,尤其是在進(jìn)行批量操作的時候。

EnumSet集合不允許加入NULL;

public class SeasonEnumSetTest {
    public static void main(String[] args) {
        //創(chuàng)建一個EnumSet集合,集合元素是Season的全部枚舉
        EnumSet enumSet = EnumSet.allOf(Season.class);
        System.out.println(enumSet);//[SPTING, SUMMER, FALL, WINTER]
        //創(chuàng)建一個空集合,指定其集合元素是Season類的枚舉類
        EnumSet noneOf = EnumSet.noneOf(Season.class);
        System.out.println(noneOf);//[]
        noneOf.add(Season.FALL);
        noneOf.add(Season.WINTER);
        System.out.println(noneOf);//[FALL, WINTER]
        //利用現(xiàn)有枚舉進(jìn)行創(chuàng)建EnumSet集合
        EnumSet of = EnumSet.of(Season.SPTING,Season.SUMMER);
        System.out.println(of);//[SPTING, SUMMER]
        //創(chuàng)建幾個從begin到end之間的枚舉作為新集合的元素
        EnumSet range = EnumSet.range(Season.SUMMER, Season.WINTER);
        System.out.println(range);//[SUMMER, FALL, WINTER]
        //range與complementof枚舉值和是Season的全部枚舉
        EnumSet complementOf = EnumSet.complementOf(range);
        System.out.println(complementOf);//[SPTING]
    }
}

當(dāng)試圖復(fù)制一個Collection集合里的元素來創(chuàng)建EnumSet集合時,必須保證Collection集合里的所有元素都是同一個枚舉類的枚舉值。

Set實現(xiàn)類的性能分析

HashSet的性能總是比TreeSet好,特別是最常用的添加,查詢元素等操作,因為TreeSet需要額外的紅黑樹算法來維護集合元素的次序,只有當(dāng)需要一個保持排序的Set時,才應(yīng)該使用TreeSet,否則都應(yīng)該使用HashSet。

LinkedHashSet對于普通的插入,刪除操作,LinkedHashSet比HashSet要略慢一點,這是由維護鏈表所帶來的額外開銷造成的,但由于有了鏈表,遍歷LinkedHashSet會更快。

EnumSet是所有Set實現(xiàn)類中性能最好的,但它只能保存同一個枚舉類的枚舉值作為集合元素。

Set的三個實現(xiàn)類HashSet,TreeSet和EnumSet都是線程不安全的。

如果有多個線程同時訪問Set集合那么需要手動保證該Set集合的同步性。

Collections.synchronizedSortedSet(new TreeSet(...));

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/69316.html

相關(guān)文章

  • java集合

    摘要:集合類簡介集合類包含在包下集合類存放的是對象的引用,而非對象本身。集合類型主要分為集,列表,映射。返回此有序集合中當(dāng)前第一個最小的元素。集合中元素被訪問的順序取決于集合的類型。 Java集合類 1.簡介: java集合類包含在java.util包下集合類存放的是對象的引用,而非對象本身。集合類型主要分為Set(集),List(列表),Map(映射)。 1.1 java集合類圖 sho...

    Pluser 評論0 收藏0
  • Java? 教程(Set接口)

    Set接口 Set是一個不能包含重復(fù)元素的Collection,它模擬了數(shù)學(xué)集抽象,Set接口僅包含從Collection繼承的方法,并添加禁止重復(fù)元素的限制,Set還為equals和hashCode操作的行為添加了一個更強的契約,允許Set實例有意義地進(jìn)行比較,即使它們的實現(xiàn)類型不同,如果兩個Set實例包含相同的元素,則它們是相等的。 Java平臺包含三個通用的Set實現(xiàn):HashSet、Tre...

    Apollo 評論0 收藏0
  • Java? 教程(集合接口)

    集合接口 核心集合接口封裝了不同類型的集合,如下圖所示,這些接口允許獨立于其表示的細(xì)節(jié)來操縱集合,核心集合接口是Java集合框架的基礎(chǔ),如下圖所示,核心集合接口形成層次結(jié)構(gòu)。 showImg(https://segmentfault.com/img/bVbntJW?w=402&h=146); Set是一種特殊的Collection,SortedSet是一種特殊的Set,依此類推,另請注意,層次結(jié)構(gòu)...

    elisa.yang 評論0 收藏0
  • 帶你入門 JavaScript ES6 (五) 集合

    摘要:一概述集合是引入的新的內(nèi)置對象類型,其特點同數(shù)學(xué)意義的集合,即集合內(nèi)所有元素不重復(fù)元素唯一。數(shù)組集合對比數(shù)組和集合,數(shù)組可以加入重復(fù)數(shù)據(jù),而集合的所有元素是唯一的不允許重復(fù)。因此,適合臨時存放一組對象,以及存放跟對象綁定的信息。 本文同步帶你入門 帶你入門 JavaScript ES6 (五) 集合,轉(zhuǎn)載請注明出處。 前面我們學(xué)習(xí)了: for of 變量和擴展語法 塊作用域變量和解構(gòu)...

    BetaRabbit 評論0 收藏0
  • Java集合框架——Map接口

    摘要:第三階段常見對象的學(xué)習(xí)集合框架集合在實際需求中,我們常常會遇到這樣的問題,在諸多的數(shù)據(jù)中,通過其編號來尋找某一些信息,從而進(jìn)行查看或者修改,例如通過學(xué)號查詢學(xué)生信息。面試題和的區(qū)別是單列集合的頂層接口,有子接口和。 第三階段 JAVA常見對象的學(xué)習(xí) 集合框架——Map集合 showImg(https://segmentfault.com/img/remote/1460000019683...

    princekin 評論0 收藏0

發(fā)表評論

0條評論

xavier

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<