Java面向?qū)ο蟆狝PI(6)----集合框架3:Set接口

1、Set接口

  • 特點(diǎn):

    無(wú)序的:不保證元素的插入次序。

    唯一:Set中存放的是對(duì)象的引用,所以相同的對(duì)象是沒(méi)法添加到集合中,即集合中不允許有相同的元素對(duì)象。主要先根據(jù)hashcode值,如果相同再看是否重寫了equals方法。

  • 注意:

    雖然Set中元素沒(méi)有順序,但是元素在set中的位置是由該元素的HashCode決定的,其具體位置其實(shí)是固定的。

2、常用實(shí)現(xiàn)類:

HashSet :

1、它不允許出現(xiàn)重復(fù)元素;不保證集合中元素的順序
2、 允許包含值為null的元素,但最多只能有一個(gè)null元素。
3、 HashSet按Hash算法來(lái)存儲(chǔ)集合的元素,因此具有很好的存取和查找性能。

  • HashSet使用和理解中容易出現(xiàn)的誤區(qū):

    a.HashSet中存放null值
    HashSet中是允許存入null值的,但是在HashSet中僅僅能夠存入一個(gè)null值。

    b.HashSet中存儲(chǔ)元素的位置是固定的
    HashSet中存儲(chǔ)的元素的是無(wú)序的,這個(gè)沒(méi)什么好說(shuō)的,但是由于HashSet底層是基于Hash算法實(shí)現(xiàn)的,使用了hashcode,所以HashSet中相應(yīng)的元素的位置是固定的。

TreeSet :

可以實(shí)現(xiàn)排序等功能的集合,它在講對(duì)象元素添加到集合中時(shí)會(huì)自動(dòng)按照某種比較規(guī)則將其插入到有序的對(duì)象序列中,并保證該集合元素組成按照“升序”排列。

TreeSet是一個(gè)有序集合,其底層是基于TreeMap實(shí)現(xiàn)的,非線程安全。TreeSet可以確保集合元素處于排序狀態(tài)。TreeSet支持兩種排序方式,自然排序和定制排序,其中自然排序?yàn)槟J(rèn)的排序方式。當(dāng)我們構(gòu)造TreeSet時(shí),若使用不帶參數(shù)的構(gòu)造函數(shù),則TreeSet的使用自然比較器;若用戶需要使用自定義的比較器,則需要使用帶比較器的參數(shù)。

  • 注意:

    TreeSet集合不是通過(guò)hashcode和equals函數(shù)來(lái)比較元素的,而是通過(guò)實(shí)現(xiàn)Comparable接口并重寫compareTo()方法或者Comparator接口的compare()來(lái)判斷元素是否相等

  • 小結(jié):

    a) 在對(duì)大量信息進(jìn)行檢索(不知道下標(biāo),比如contains)的時(shí)候,TreeSet比ArrayList更有效率。
    b) TreeSet是用樹形結(jié)構(gòu)來(lái)存儲(chǔ)信息的,每個(gè)節(jié)點(diǎn)都會(huì)保存一下指針對(duì)象,分別指向父節(jié)點(diǎn),左分支,右分支,相比較而言,ArrayList就是一個(gè)含有元素的簡(jiǎn)單數(shù)組了,正因?yàn)槿绱?,它占的?nèi)存也要比ArrayList多一些。
    c) 想TreeSet插入元素也比ArrayList要快一些,因?yàn)楫?dāng)元素插入到ArrayList的任意位置時(shí),平均每次要移動(dòng)一半的列表(普遍的都是,set查詢慢,插入快,list查詢快,插入慢)。

3、示例代碼

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class TestHashSet {

    public static void main(String[] args) {
        // HashSet的基本用法

        // Set集合特點(diǎn):
        // 1、存儲(chǔ)的元素是無(wú)序(不是添加的順序),且唯一(不可重復(fù))

        // 創(chuàng)建Set集合對(duì)象
        Set<String> carSet = new HashSet<>();

        // 添加元素:add(Object obj)
        System.out.println("------------------- 無(wú)序 -------------------");
        carSet.add("Audi");
        carSet.add("Benz");
        carSet.add("Bmw");
        carSet.add("Volvo");
        System.out.println("carSet集合元素:" + carSet);
        System.out.println("------------------- 唯一 -------------------");
        carSet.add("Volvo");
        System.out.println("carSet集合元素:" + carSet);

        // 擴(kuò)展:能不能存放null元素?可以,數(shù)量只有一個(gè)
        System.out.println("------------------- null -------------------");
        carSet.add(null);
        carSet.add("Byd");
        carSet.add(null);
        System.out.println("carSet字符串集合元素:" + carSet);

        // 獲取元素:get(index),沒(méi)有此方法,set集合是無(wú)序,元素沒(méi)有下標(biāo),沒(méi)有根據(jù)下標(biāo)獲取元素的方法
        // carSet.get(0); // 編譯不通過(guò),沒(méi)有此方法

        // 獲取元素個(gè)數(shù):size() , 返回集合中元素個(gè)數(shù)
        System.out.println("------------------- size -------------------");
        System.out.println("carSet字符串集合元素個(gè)數(shù):" + carSet.size());

        // 判斷是否包含某個(gè)元素:contains(Object obj),如果包含指定元素,返回true,否則返回false
        System.out.println("------------------- contains -------------------");
        System.out.println("carSet字符串集合是否包含Bmw?:" + carSet.contains("Bmw"));

        // 其它的集合操作方法,比如判斷非空,清空等,不一一介紹,課后自行測(cè)試

        // 遍歷集合中的元素:
        // 方式1:使用迭代器
        System.out.println("------------------- 迭代器遍歷 -------------------");
        Iterator<String> carIterator = carSet.iterator();
        while (carIterator.hasNext()) {
            System.out.println("carSet中的元素:" + carIterator.next());
        }

        // 方式2:增強(qiáng)for循環(huán),普通for無(wú)法實(shí)現(xiàn)
        System.out.println("------------------- 增強(qiáng)for遍歷 -------------------");
        for (String carStr : carSet) {
            System.out.println("carSet中的元素:" + carStr);
        }

        // 探討:Set集合中,存儲(chǔ)的元素是唯一的,重復(fù)的元素如何保證唯一?是覆蓋重復(fù)元素還是加不進(jìn)去?
        // 不是覆蓋,先判斷元素的hashCode值,如果相同,再判斷equals是否相同,如果相同,不添加
        // 創(chuàng)建SetUnique對(duì)象1
        SetUnique setUnique1 = new SetUnique();
        setUnique1.setSetScore(100);
        // 創(chuàng)建SetUnique對(duì)象2
        SetUnique setUnique2 = new SetUnique();
        setUnique2.setSetScore(150);

        System.out.println("------------------- -------------------");
        System.out.println("== 判斷 setUnique1和setUnique2是否是同一個(gè)對(duì)象?" + (setUnique1 == setUnique2));
        System.out.println("equals 判斷 setUnique1和setUnique2是否是同一個(gè)對(duì)象?" + (setUnique1.equals(setUnique2)));

        // 創(chuàng)建set集合,添加元素
        Set<SetUnique> setUniques = new HashSet<>();
        setUniques.add(setUnique1);
        setUniques.add(setUnique2);

        System.out.println("setUniques中元素:" + setUniques);

    }
}

/**
 * Set唯一特性測(cè)試類
 * 
 * @author xiayimiaoyijiuyonggan
 *
 */
public class SetUnique {

    private int setScore;

    public int getSetScore() {
        return setScore;
    }

    public void setSetScore(int setScore) {
        this.setScore = setScore;
    }

    @Override
    public int hashCode() {
        // 重新hashCode
        // 場(chǎng)景1:setScore值作為hashCode值,
        // return this.setScore;

        // 場(chǎng)景2:自定義一個(gè)邏輯,確保不同的setScore,返回相同的hashCode
        return this.setScore / 100;

    }

    @Override
    public boolean equals(Object obj) {
        // 重寫equals方法
        // TODO 參數(shù)非空,類型判斷(instanceOf)不做了
        // 場(chǎng)景1:默認(rèn)不管setScore是否相同,默認(rèn)都是同一個(gè)對(duì)象,hashCode值不同,即便equals相同也是不同對(duì)象
        return true;

        // 場(chǎng)景2:自定義一個(gè)邏輯,根據(jù)setScore判斷是否是同一個(gè)對(duì)象,如果setScore相同,就是同一個(gè)對(duì)象,不同就不是同一個(gè)對(duì)象
        // hashCode值相同,會(huì)判斷equals是否相同,如果相同就是同一個(gè)對(duì)象,如果不同就不是同一個(gè)對(duì)象
        /*
         * SetUnique setUnique = (SetUnique) obj; // 判斷setScore值是否相同 if
         * (this.setScore != setUnique.getSetScore()) { // 不是同一個(gè)對(duì)象 return false;
         * }
         * 
         * // 同一個(gè)對(duì)象 return true;
         */
    }
    
    @Override
    public String toString() {
        return "SetUnique [setScore=" + setScore + "]";
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容