Collection接口之Set接口

摘要:

在java中集合主要分為兩類阀蒂,collection和map兩個(gè)大的接口锦针,collection又分為list和set接口荠察,這里記錄set接口的基本使用奈搜,供自己隨時(shí)查看。

set的特點(diǎn):

set存儲(chǔ)的數(shù)據(jù)是無(wú)序的馋吗,不可重復(fù)的。set接口是collection的子接口宏粤,set接口沒(méi)有提供額外的方法灼卢,set元素不允許包含相同的元素(無(wú)序不可重復(fù)),set判斷兩個(gè)對(duì)象是不是相等不是使用==運(yùn)算符鞋真,而是根據(jù)equals方法

Set的主要實(shí)現(xiàn)類:

  • HashSet(set接口是主要實(shí)現(xiàn)類,是線程不安全的沃于,可以存儲(chǔ)null值)
  • LinkHashSet(是HashSet的子類涩咖,意思是在HashSet的基礎(chǔ)上添加了前后指針,使其遍歷時(shí)可以讓他按照添加的順序進(jìn)行遍歷繁莹,讓他看起來(lái)像是有序一樣檩互,但實(shí)際是一種假象)
  • TreeSet(底層是二叉樹(shù),具體一點(diǎn)就是紅黑樹(shù)(樹(shù)結(jié)構(gòu)本身就是有序的)咨演,他要求放入treeset中的對(duì)象是同一個(gè)類的對(duì)象盾似,可以按照添加對(duì)象的指定屬性進(jìn)行排序)

set中常用的方法,Set接口沒(méi)有提供額外的方法雪标,因此set接口的操作方法都是在collection中定義的。

Set集合的基本使用示例

public class SetTest{
  @Test
  public void test() {
    Set set = new HashSet();
  
   set.add(456);
   set.add(123);
   set.add("AA");
   set.add("CC");
   set.add(new Person("tom", 123));
   set.add(123);
   set.add(new User("tom", 123));
   set.add(new User("name",123));
   Iterator iterator = set.iterator();
   while(iterator.hasNext()) {
          System.out.println(iterator.next());
    }
  }
}
// 打印的結(jié)果為:
AA
CC
Person{name='tom', age=123}
456
User{name='name', age=123}
123
User{name='tom', age=123}
set結(jié)構(gòu)的無(wú)序性:
得到的結(jié)果并不是按照添加的順序來(lái)的溉跃,然而這便不是巧合村刨,
其實(shí)每次遍歷的得到的結(jié)果都是這個(gè)值,并不是隨機(jī)性的撰茎,
這是因?yàn)榍段m然Set的數(shù)據(jù)最終也是通過(guò)數(shù)組存的
,但是在存儲(chǔ)的時(shí)候并不是按照數(shù)組的索引來(lái)添加的龄糊,
而是根據(jù)數(shù)據(jù)的hash值來(lái)決定的逆粹,這就是set的無(wú)序性。
加的元素不是按照數(shù)組中的順序一個(gè)個(gè)來(lái)的炫惩,而是通過(guò)魔種算法來(lái)確定添加的元素是
 再數(shù)組中的哪一個(gè)位置

set結(jié)構(gòu)的不可重復(fù)性:
由例子中的結(jié)果可知僻弹,相同的元素并沒(méi)有被添加到set中,這是set不可重復(fù)性的體現(xiàn)他嚷,就是相同的元素只能添加一個(gè)蹋绽,具體的判斷方案是equals()方法不能返回true,如果是則添加不進(jìn)去。

向Set集合中添加元素的過(guò)程:

我們向HashSet中添加元素a筋蓖,首先調(diào)用元素a所在類的hansCode方法卸耘,計(jì)算元素a的hash值,此hash值接著通過(guò)某種算法算出再HashSet底層數(shù)組中存放的位置(即為相應(yīng)的索引位置)粘咖,判斷數(shù)組此位置上是否已經(jīng)有元素蚣抗,如果此位置沒(méi)有元素,則元素小a直接添加成功瓮下,如果有其他元素b(或者以鏈表形式存在的多個(gè)元素翰铡,)钝域,則比較
元素a和b的hash值,若果hash值不相同两蟀,則元素a添加成功网梢,如果hash相同,則需要調(diào)用元素a所再類的equals方法赂毯,如果返回true,則添加失敗战虏,如果返回false,則添加成功。

Set集合中注意事項(xiàng):

  • 1HashSet集合判斷兩個(gè)元素相等的標(biāo)準(zhǔn)是兩個(gè)對(duì)象的hashCode方法比較 相等党涕,并且兩個(gè)對(duì)象的equals方法的返回值也是相等的。
  • .2. 于存放在Set容器中的對(duì)象膛堤,對(duì)應(yīng)的類一定要重寫(xiě)equals()和hashCode方法。以實(shí)現(xiàn)對(duì)象的氙燈規(guī)則绿渣,即相等的對(duì)象必須有相等的散列碼
  • 3 LinkedHashSet是作為HashSet的子類燕耿,再添加數(shù)據(jù)的同時(shí),每個(gè)數(shù)據(jù)還維護(hù)了兩個(gè)引用淀散,記錄次數(shù)據(jù)的前一個(gè)數(shù)組和后一個(gè)數(shù)組蚜锨,對(duì)于頻繁的遍歷操作,用LikedHashSet效率高
  • 4 LinkedHashSet遍歷時(shí)是按照添加的順序遍歷的亚再,但是并不能說(shuō)LinkedHashSet是有序的,因?yàn)長(zhǎng)inkedHashSet在添加數(shù)據(jù)的時(shí)候還維護(hù)了兩個(gè)引用饲鄙。
  • 5 之前提到Set中元素標(biāo)膠相等是通過(guò)hashCode方法和equals方法來(lái)決定的忍级,但是TreeSet作為Set接口的實(shí)現(xiàn)類卻是一個(gè)例外伪朽。TreeSet比較相是更具排序來(lái)決定的,而且TreeSet中添加的元素是同一類型的元素朴肺,因?yàn)樾枰容^大小,如果不是同一類型的元素就沒(méi)有辦法比較大小西土,而且會(huì)報(bào)錯(cuò)鞍盗。

兩種常見(jiàn)的排序方式。

  • 自然排序(實(shí)現(xiàn)Comparable接口):比較兩個(gè)對(duì)象是否相同的標(biāo)準(zhǔn)是:compareTo返回0
  • 定制排序(和Comparator相關(guān)):標(biāo)膠兩個(gè)對(duì)象是否相等的標(biāo)準(zhǔn)是:compare返回0
    如:
package com.liquan.exer;

import org.junit.Test;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * @auth nan
 * @create 2019-12-28 11:21
 */
public class SetDemo1 {

    /**
     * 在list內(nèi)去除重復(fù)數(shù)字肋乍,要求盡量簡(jiǎn)單
     */

    @Test
    public void test(){

        List list = new ArrayList();
        list.add(new Integer(1));
        list.add(new Integer(2));
        list.add(new Integer(3));
        list.add(new Integer(4));
        list.add(new Integer(4));
        HashSet set = new HashSet();

        set.addAll(list);

        List list2 = new ArrayList(set);

        for (Object integer: list2){
            System.out.println(integer);
        }

    }
}


Set集合使用的綜合案例

  • 利用Set的特性去重List
public class SetDemo1 {

    

    @Test
    public void test(){

        List list = new ArrayList();
        list.add(new Integer(1));
        list.add(new Integer(2));
        list.add(new Integer(3));
        list.add(new Integer(4));
        list.add(new Integer(4));
        HashSet set = new HashSet();

        set.addAll(list); // 相同的元素是添加不進(jìn)去的

        List list2 = new ArrayList(set);

        for (Object integer: list2){
            System.out.println(integer);
        }

    }
}

  • 對(duì)于set無(wú)序和不可重復(fù)的加深理解案例
package com.liquan.exer;

import org.junit.Test;

import java.util.HashSet;



public class SetDemo2 {
    // 對(duì)于set一點(diǎn)先要equals
    @Test
    public void test(){
        Person p1 = new Person(1, "AA");
        Person p2 = new Person(2, "BB");

        HashSet set = new HashSet();

        set.add(p1);
        set.add(p2);

        System.out.println(set); // [Person{id=1, name='AA'}, Person{id=2, name='BB'}]

        p1.name = "CC";
        set.remove(p1);
        System.out.println(set); // 在重寫(xiě)hashCode和equals方法的前提下得到的是[Person{id=1, name='CC'}, Person{id=2, name='BB'}]
        // 因?yàn)閞emove在移除的時(shí)候判斷存在才移除媒区,判斷存在則需要去找觅闽,更具h(yuǎn)ash值去找對(duì)應(yīng)的位置谱煤,在移除前p1.name是CC,所以會(huì)用CC
        // 去得到一個(gè)hash值禽拔,此時(shí)得到的hash值和AA得到hash值不一樣室叉,此時(shí)根據(jù)這個(gè)hash值找到的內(nèi)存地址并沒(méi)有值,所以并沒(méi)有真正意義上的
        // 刪除茧痕。所以此時(shí)還是原來(lái)的兩個(gè)值,只不過(guò)AA被換成了CC.

        set.add(new Person(1, "CC")); // 同樣能添加成功

        System.out.println(set); // [Person{id=1, name='CC'}, Person{id=1, name='CC'}, Person{id=2, name='BB'}]
        // 因?yàn)樘砑拥臅r(shí)候按CC去計(jì)算hash值踪旷,得到的hash值得地方并沒(méi)有值存儲(chǔ),因此能添加成功

        set.add(new Person(1, "AA")); // 同樣能添加成功
        System.out.println(set); // [Person{id=1, name='CC'}, Person{id=1, name='CC'}, Person{id=1, name='AA'}, Person{id=2, name='BB'}]

        // 因?yàn)殡m然拿AA得到的hash值的地方有值令野,但是通過(guò)equals的時(shí)候CC和AA不一樣,所以同樣能添加成功气破。

    }
}


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市低匙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欺抗,老刑警劉巖强重,帶你破解...
    沈念sama閱讀 223,207評(píng)論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異报强,居然都是意外死亡拱燃,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門召嘶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)哮缺,“玉大人,你說(shuō)我怎么就攤上這事铛只】妨铮” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 170,031評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵蜕着,是天一觀的道長(zhǎng)承匣。 經(jīng)常有香客問(wèn)我锤悄,道長(zhǎng),這世上最難降的妖魔是什么宽闲? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,334評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮娩梨,結(jié)果婚禮上览徒,老公的妹妹穿的比我還像新娘。我一直安慰自己习蓬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布芦缰。 她就那樣靜靜地躺著让蕾,像睡著了一般或听。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上顿颅,一...
    開(kāi)封第一講書(shū)人閱讀 52,895評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音斩跌,去河邊找鬼。 笑死滔驶,一個(gè)胖子當(dāng)著我的面吹牛卿闹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播著角,決...
    沈念sama閱讀 41,300評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼吏口,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了产徊?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,264評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤戈盈,失蹤者是張志新(化名)和其女友劉穎谆刨,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體痊夭,經(jīng)...
    沈念sama閱讀 46,784評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡她我,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評(píng)論 3 343
  • 正文 我和宋清朗相戀三年鸦难,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片合蔽。...
    茶點(diǎn)故事閱讀 40,989評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拴事,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衡瓶,到底是詐尸還是另有隱情,我是刑警寧澤哮针,帶...
    沈念sama閱讀 36,649評(píng)論 5 351
  • 正文 年R本政府宣布坦袍,位于F島的核電站,受9級(jí)特大地震影響蛮放,放射性物質(zhì)發(fā)生泄漏奠宜。R本人自食惡果不足惜瞻想,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評(píng)論 3 336
  • 文/蒙蒙 一娩嚼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧漠其,春花似錦和屎、人聲如沸春瞬。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,814評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)萄涯。三九已至,卻和暖如春涝影,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背序目。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,940評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工猿涨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姆怪。 一個(gè)月前我還...
    沈念sama閱讀 49,452評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像稽揭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Java集合類可用于存儲(chǔ)數(shù)量不等的對(duì)象,并可以實(shí)現(xiàn)常用的數(shù)據(jù)結(jié)構(gòu)如棧,隊(duì)列等,Java集合還可以用于保存具有映射關(guān)...
    小徐andorid閱讀 1,946評(píng)論 0 13
  • 上一篇文章介紹了Set集合的通用知識(shí)膨桥。Set集合中包含了三個(gè)比較重要的實(shí)現(xiàn)類:HashSet、TreeSet和En...
    Ruheng閱讀 15,653評(píng)論 3 57
  • 集合類框架的介紹: ![Java 集合類框架](https://upload-images.jianshu.io/...
    LynnGuo閱讀 755評(píng)論 0 1
  • Java集合框架 Java平臺(tái)提供了一個(gè)全新的集合框架〔嵛瑁“集合框架”主要由一組用來(lái)操作對(duì)象的接口組成蕴掏。不同接口描述...
    小石38閱讀 362評(píng)論 0 0
  • 在編程中盛杰,常常需要集中存放多個(gè)數(shù)據(jù)藐石。集合類主要負(fù)責(zé)保存、盛裝其他數(shù)據(jù)于微,因此集合類也被稱為容器類。所有的集合類都位于...
    一一一二二三閱讀 411評(píng)論 0 1