菜鳥學JAVA之——集合框架(二)(Set接口的實現類HashSet、LinkedHashSet、TreeSet)

Set接口

如果有人告訴你Set是無序的,那你可以直接回懟他這是錯的,說法不嚴謹。

Set接口的實現類(都不能放重複值)

​ 1.HashSet(無序)

​ 2.LinkedHashSet(有序)

​ 3.TreeSet(有序)

沒有ArraySet,這是因爲Array是連續的,Set是不連續的;

  • Set與List的相同點,也是Collection的子接口,也是容器

  • Set才叫真正意義上的集合,List叫做列表

  • 集合與列表的區別:

    列表是一條一條記錄的,而集合是圍在一起的

    比如,有五個人,他們整整齊齊做一列就是列表,要是圍一堆坐着就是集合,不知道誰是頭,誰是尾

    Set集合是沒有腳標的,所以Set裏面也沒有get方法,List有腳標,所以可以有get方法,List和Set是兄弟關係,這也正是Collection接口裏沒有get方法的原因。

  • 集合中不能放重複的對象,這是因爲他沒有腳標。所以Set集合可用來去重

  • Set有點像水壺,茶壺裏煮餃子,倒不出來。要是想從Set裏拿出來,則必須把所有的值都拿出來

HashSet是無序的,注意是HashSet不是Set

forezch在底層使用迭代器實現的

如果一個類沒有迭代器,則它不能使用foreach循環

iterator.remove();不能連着使用

  • 怎麼解釋hashset是無序的,怎麼解釋set不能放重複元素?

    因爲hashSet的底層是按照hash算法排列得到的數列,他是一個不可逆的算法。每個對象都有一個hashcode,hash算法通過hashcode來排數據,所以hashset無序。

    HashSet底層由HashMap實現,插入的元素被當做是HashMap的key,根據hashCode值來確定集合中的位置,在向HashMap中添加元素時,先判斷key的hashCode值是否相同,如果相同,則調用equals()、==進行判斷,若相同則覆蓋原有元素;如果不同,則直接向Map中添加元素;

set的兩個主要實現類,TreeSet和HashSet,底層存儲結構都是用的map,而且是將set需要存儲的值放在map的key裏的,value是一個空的object對象。

在這裏插入圖片描述

  • 那有沒有有序的set呢

    有,LinkedHashSet, 往裏放的什麼順序,打印出來的就是什麼順序,以鏈表的形式存當前的元素,只是鏈表位置被hash了,但是它沒有下標

    還有一個有序的set,TreeSet。按comparable升序排列,它的底層實現是二叉樹

TreeSet有個約束,往它裏面放到內容必須實現comparable接口

一、HashSet

在向HashMap中添加元素時,先判斷key的hashCode值是否相同,如果相同,則調用equals()、==進行判斷,若相同則覆蓋原有元素;如果不同,則直接向Map中添加元素;

public class Main {
    public static void main(String[] args) {
        Set<String> sets = new HashSet<>();
        sets.add("zhang");
        sets.add("ao");
        sets.add("qi");
        sets.add("zhang");
        sets.add("san");
        Iterator<String> iterator = sets.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        } //輸出:san   qi    zhang   ao  //無序的且不重複
        sets.remove("ao");//刪除元素
        sets.clear(); //清空容器
    }
}

二、LinkedHashSet(直接父類是 HashSet)

特點:存取有序,存儲的元素不能重複。

Set<String> sets = new LinkedHashSet<>();
        sets.add("a");
        sets.add("a");
        sets.add("a");
        sets.add("b");
        sets.add("b");
        sets.add("c");
        sets.add("d");
        for (String str:sets
             ) {
            System.out.println(str);
        }
//輸出a   b   c   d

三、TreeSet( 底層結構爲紅黑樹

與HashSet不同的是,TreeSet具有排序功能,分爲自然排序(123456)和自定義排序兩類,默認是自然排序;在程序中,我們可以按照任意順序將元素插入到集合中,等到遍歷時TreeSet會按照一定順序輸出–倒序或者升序;

方式一: 讓元素所在的類實現Comparable接口,並重寫CompareTo() 方法,並根據CompareTo()的返回值來進行添加元素

  • 返回正數:往二叉樹的右邊添加
  • 返回負數:往二叉樹的左邊添加
  • 返回 0 : 說明重複,不添加

方式二: 使用TreeSet的有參構造方法創建TreeSet對象的時候, 傳入一個比較器 Comparator 進去, TreeSet在添加元素的時候, 根據比較器的compare()方法的返回值來添加元素。

  • 返回正數:往二叉樹的右邊添加
  • 返回負數:往二叉樹的左邊添加
  • 返回 0 : 說明重複,不添加

TreeSet存儲元素對元素進行排序的源碼解析
TreeSet在存儲元素的時候會首先去判斷是否有比較器存在(也就是判斷比較器是否爲null),如果存在:就會讓比較器去調用compare(T t1, T t2)方法,去依次比較即將存入的值和已經存入TreeSet集合的值,如果返回正數:往二叉樹右側放;如果返回負數:往二叉樹左側放;如果返回 0 :不添加。如果不存在:底層就會把即將存入的元素自動提升爲Comparable類型的對象(所以如果沒有比較器的情況下,元素所在的類沒有實現Comparable接口,在做自動提升類型的時候就會報類型轉換錯誤),並讓該對象調用CompareTo(T t)方法,和已經存入TreeSet集合的元素依次比較,如果返回正數:往二叉樹右側放;如果返回負數:往二叉樹左側放;如果返回 0 :不添加。所以,如果兩種方式同時使用,底層會優先使用方式二(比較器的方式)。
在這裏插入圖片描述

學習參考:
https://blog.csdn.net/Qingai521/article/details/87968134
https://www.baidu.com/link?url=o4mGbw9BArl9kO8SxYj_9jYdwjO5FsfggK8FpB6CCxsj1SxlIhSRsx7_3mAu_2F3&wd=&eqid=a848f8fb0007e998000000035dfaf2c7

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章