java集合-Set

一设联、Set集合特性

  • Set集合不允許存儲重復(fù)元素
  • 無序集合顽冶,存儲的順序和取出順序不同
  • 沒有下標(biāo)
  • 使用傳統(tǒng)的for遍歷,可以用增強for破喻,迭代器
  • Set接口方法订咸,和父接口Collection的方法曼尊,完全一致

二、接口特點和存取

直接上demo脏嚷,用HashSet實例化

/*
 * Set集合的練習(xí)骆撇,包括特點接存取
 */
import java.util.*;

public class SetDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();

        set.add("agk");
        set.add("ghkjrtykh");
        set.add("c");
        set.add("yuiyd");

        for (String s : set) {
            System.out.println(s);
        }

        System.out.println("---------------------");

        // 迭代器遍歷
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

三、HashSet集合

HashSet哈希表父叙,無序神郊,允許null,線程不安全趾唱,查詢速度快涌乳,不重復(fù)。

那么HashSet如何保證對象唯一性的呢甜癞?HashSet底層實現(xiàn)原理是哈希表夕晓,存儲的是對象的哈希值。集合的內(nèi)部悠咱,存儲的就是對象的哈希值蒸辆,成為哈希表,是一個巨大的容器析既,會為每一個哈希值開辟獨立存儲空間躬贡。

HashSet集合的存儲對象過程:存儲對象的時候,調(diào)用該對象的hashCode方法眼坏,取得哈希值拂玻,自己的容器中是否有了這個哈希值?如果沒有宰译,直接將哈希值存儲自己的容器檐蚜。如果有了,調(diào)用對象的equals方法囤屹,和已經(jīng)存儲在的對象熬甚,進行比較,結(jié)果是真肋坚,HashSet判斷為同一對象乡括,不存肃廓。結(jié)果是假,將后進來的對象诲泌,掛靠在先進來的對象之后盲赊。

結(jié)論:HashSet集合保證對象的唯一性,依據(jù)對象的hashCode和equals方法敷扫,要求存儲到哈希表中的對象哀蘑,必須重寫hashCode和equals方法

兩個問題:

  1. 兩個對象,如果對象的哈希值相同葵第,equals方法一定返回真嗎绘迁?

    不一定,不同對象的哈希值有一定概率相同

  2. 兩個對象卒密,如果equals返回真缀台,hashCode的值一定相同嗎?

    一定哮奇,兩種情況膛腐。地址相同,指向同一個對象鼎俘,這個哈希值一定相同哲身。內(nèi)容相容,地址不同贸伐,此時哈希值也一定相同勘天。

demo:

package SetDemo;
/*
 * HashSet的特點
 */
import java.util.*;

public class SetDemo1 {
    public static void main(String[] args) {
        HashSet<Person> set = new HashSet<Person>();
        set.add(new Person("a",16));
        set.add(new Person("a",11));
        set.add(new Person("b",10));
        set.add(new Person("c",15));
        set.add(new Person("c",15));
        
        //Person重寫了hashCode方法和equals方法
        //不同的對象,hash值有可能相同捉邢,所以又要調(diào)用equals方法進行比較误辑,相同則拋棄,否則掛在之前對象的后面
        
        for(Person p : set){
            System.out.println(p);
        }
        
        HashSet<Integer> set2 = new HashSet<Integer>();
        set2.add(new Integer(1231));
        set2.add(new Integer(1231));
        System.out.println(set2);

    }
}
//================================分割線=========================================================
//附person代碼歌逢,注意兩個類不在同一個java文件內(nèi)
package SetDemo;

/*
 * 一個自定義Person對象
 */
public class Person {

    private String name;
    private int age;

    Person() {
    }

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null)
            return false;
        if (o instanceof Person) {
            Person p = (Person) o;
            return this.name.equals(p.name) && this.age == p.age;
        }
        return false;
    }

    public String toString() {
        return this.name + "..." + this.age;
    }

    public int hashCode() {
        return name.hashCode() + age * 2;
    }
}

四、LinkedHashSet有序集合

具有迭代順序的Set集合翘狱,是HashSet的子類秘案,開始版本是JDK1.4。線程不安全的潦匈,效率快阱高,基于鏈表的哈希表。

demo:

/*
 * 有序的Set集合
 * 保證存儲和取出的順序一致
 */
import java.util.*;
public class LinkedHashSetDemo {
    public static void main(String[] args) {
        LinkedHashSet<String> lhs = new LinkedHashSet<String>();
        lhs.add("abc");
        lhs.add("tgf");
        lhs.add("weds");
        lhs.add("gvfcd");
        lhs.add("qwds");
        for(String s : lhs){
            System.out.println(s);
        }
    }
}

/*輸出如下:
abc
tgf
weds
gvfcd
qwds
*/

五茬缩、TreeSet集合

對存儲的對象赤惊,按照自然順序進行排序,同時也是線程不安全凰锡。

存儲對象到TreeSet集合中未舟,出現(xiàn)了類型轉(zhuǎn)換異常圈暗,不能被轉(zhuǎn)成java.lang.Comparable類型問題。Comparable是一個接口裕膀,如果類實現(xiàn)了此接口员串,定義的類具有了自然順序。TreeSet排序必須按照對象的自然順序昼扛。

此時要是存儲自定義對象時寸齐,就需要實現(xiàn)接口Comparable,demo如下:

package SetDemo;
import java.util.*;
/*
 * TreeSet存儲自定義對象Person
 */
public class TreeSetDemo {
    public static void main(String[] args) {
        //實現(xiàn)存儲自定義對象
        TreeSet<Person> tp = new TreeSet<Person>();
        
        tp.add(new Person("liuchao",12));
        tp.add(new Person("liuyifei",12));
        tp.add(new Person("linxu",12));
        tp.add(new Person("liuqinfei",12));
        tp.add(new Person("liuqinfei",13));
        
        System.out.println(tp);
    }
}
/*
程序的輸出結(jié)果為:[linxu...12, liuchao...12, liuqinfei...12, liuqinfei...13, liuyifei...12]
*/
//附Person類新添加的代碼
package SetDemo;

/*
 * 一個自定義Person對象
 */
public class Person implements Comparable<Person>{
  ...
    //比較的方法是:先按名字的自然順序排序抄谐,相同再按年輕排序渺鹦,都是小的在左,大的在右
    public int compareTo(Person p){
        int num = this.name.compareTo(p.name);
        if(num == 0)
            return this.age-p.age;
        return num;

    }
  ...
}

1. 比較器-comparator

上述的Person類實現(xiàn)了接口Comparable蛹含,重寫了compareTo方法毅厚。但是此時有一個局限性,那就是如果想換一種排序的方法就會比較麻煩挣惰,需要重寫compareTo方法卧斟。其實不然,此時其實還有一個接口叫comparator憎茂,在初始化TreeSet時只要將比較器當(dāng)作參數(shù)傳入即可使用新的排序方法珍语。

下面舉例實現(xiàn),首先實現(xiàn)一個比較器(繼續(xù)以之前的Person類為例)

package SetDemo;
import java.util.Comparator;
/*
 * 構(gòu)建Person的比較器竖幔,優(yōu)先按照年齡排序板乙,年齡相同則使用名字排序
 */
public class PersonComparator implements Comparator<Person> {   
    public int compare(Person p1, Person p2){       
        int num = p1.getAge()-p2.getAge();  
        return num == 0 ? p1.getName().compareTo(p2.getName()) : num;
    }
}

然后更改下之前的代碼:

package SetDemo;
import java.util.*;
/*
 * TreeSet存儲自定義對象Person
 */
public class TreeSetDemo {
    public static void main(String[] args) {
      
//同時,也可以自定義比較器拳氢,傳入TreeSet()方法中即可使用傳入的比較器比較募逞,而放棄原來的默認方法compareTo
        TreeSet<Person> tp = new TreeSet<Person>(new PersonComparator());
        
        tp.add(new Person("liuchao",12));
        tp.add(new Person("liuyifei",19));
        tp.add(new Person("linxu",12));
        tp.add(new Person("liuqinfei",12));
        tp.add(new Person("liuqinfei",0));
        
        System.out.println(tp);
    }
}
/*程序輸出如下,可以看到已經(jīng)優(yōu)先按照年齡排序了
[liuqinfei...0, linxu...12, liuchao...12, liuqinfei...12, liuyifei...19]
*/
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末馋评,一起剝皮案震驚了整個濱河市放接,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌留特,老刑警劉巖纠脾,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蜕青,居然都是意外死亡苟蹈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門右核,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慧脱,“玉大人,你說我怎么就攤上這事贺喝×馀福” “怎么了宗兼?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長采缚。 經(jīng)常有香客問我针炉,道長,這世上最難降的妖魔是什么扳抽? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任篡帕,我火速辦了婚禮,結(jié)果婚禮上贸呢,老公的妹妹穿的比我還像新娘镰烧。我一直安慰自己,他們只是感情好楞陷,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布怔鳖。 她就那樣靜靜地躺著,像睡著了一般固蛾。 火紅的嫁衣襯著肌膚如雪结执。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天艾凯,我揣著相機與錄音献幔,去河邊找鬼。 笑死趾诗,一個胖子當(dāng)著我的面吹牛蜡感,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播恃泪,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼郑兴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了贝乎?” 一聲冷哼從身側(cè)響起情连,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎览效,沒想到半個月后蒙具,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡朽肥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了持钉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衡招。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖每强,靈堂內(nèi)的尸體忽然破棺而出始腾,到底是詐尸還是另有隱情州刽,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布浪箭,位于F島的核電站穗椅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏奶栖。R本人自食惡果不足惜匹表,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宣鄙。 院中可真熱鬧袍镀,春花似錦、人聲如沸冻晤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鼻弧。三九已至设江,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間攘轩,已是汗流浹背叉存。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留撑刺,地道東北人鹉胖。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像够傍,于是被迫代替她去往敵國和親甫菠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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

  • 1.Set 上一篇冕屯,我們介紹Java中的List集合寂诱。本篇,讓我們繼續(xù)學(xué)習(xí)安聘,來了解下Set集合痰洒; Set繼承于Co...
    賈博巖閱讀 83,648評論 4 52
  • 上一篇文章介紹了Set集合的通用知識。Set集合中包含了三個比較重要的實現(xiàn)類:HashSet浴韭、TreeSet和En...
    Ruheng閱讀 15,639評論 3 57
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法丘喻,類相關(guān)的語法,內(nèi)部類的語法念颈,繼承相關(guān)的語法泉粉,異常的語法,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • 1 Set集合主要源碼分析 上一篇,我們介紹了Java集合框架中的Set集合嗡靡,主要講了HashSet和TreeSe...
    賈博巖閱讀 1,214評論 0 6
  • Java集合框架 Java平臺提供了一個全新的集合框架跺撼。“集合框架”主要由一組用來操作對象的接口組成讨彼。不同接口描述...
    小石38閱讀 360評論 0 0