集合(中)LinkedList、HashSet、Collection總結

  • List集合存儲數據的結構

數據存儲的常用結構有:堆棧、隊列、數組、鏈表。我們分別來了解一下:

堆棧,採用該結構的集合,對元素的存取有如下的特點:

先進後出(即,存進去的元素,要在後它後面的元素依次取出後,才能取出該元素)。例如,子彈壓進彈夾,先壓進去的子彈在下面,後壓進去的子彈在上面,當開槍時,先彈出上面的子彈,然後才能彈出下面的子彈。

棧的入口、出口的都是棧的頂端位置

壓棧:就是存元素。即,把元素存儲到棧的頂端位置,棧中已有元素依次向棧底方向移動一個位置。

彈棧:就是取元素。即,把棧的頂端位置元素取出,棧中已有元素依次向棧頂方向移動一個位置。

 

隊列,採用該結構的集合,對元素的存取有如下的特點:

先進先出(即,存進去的元素,要在後它前面的元素依次取出後,才能取出該元素)。例如,安檢。排成一列,每個人依次檢查,只有前面的人全部檢查完畢後,才能排到當前的人進行檢查。

隊列的入口、出口各佔一側。例如,下圖中的左側爲入口,右側爲出口。

 

數組,採用該結構的集合,對元素的存取有如下的特點:

查找元素快:通過索引,可以快速訪問指定位置的元素

增刪元素慢:

指定索引位置增加元素:需要創建一個新數組,將指定新元素存儲在指定索引位置,再把原數組元素根據索引,複製到新數組對應索引的位置。如下圖

指定索引位置刪除元素:需要創建一個新數組,把原數組元素根據索引,複製到新數組對應索引的位置,原數組中指定索引位置元素不復制到新數組中。如下圖

 

鏈表,採用該結構的集合,對元素的存取有如下的特點:

多個節點之間,通過地址進行連接。例如,多個人手拉手,每個人使用自己的右手拉住下個人的左手,依次類推,這樣多個人就連在一起了。

查找元素慢:想查找某個元素,需要通過連接的節點,依次向後查找指定元素

增刪元素快:

增加元素:操作如左圖,只需要修改連接下個元素的地址即可。

刪除元素:操作如右圖,只需要修改連接下個元素的地址即可。

        

        

  • LinkedList集合

        LinkedList集合數據存儲的結構是鏈表結構。方便元素添加、刪除的集合。實際開發中對一個集合元素的添加與刪除經常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。如下圖

在開發時,LinkedList集合也可以作爲堆棧,隊列的結構使用。


  • Set接口

    HashSet集合介紹

    查閱HashSet集合的API介紹:此類實現Set接口,由哈希表支持(實際上是一個 HashMap集合)。HashSet集合不能保證的迭代順序與元素存儲順序相同。

    HashSet集合,採用哈希表結構存儲數據,保證元素唯一性的方式依賴於:hashCode()equals()方法。

    HashSet集合存儲數據的結構(哈希表)

    什麼是哈希表呢?

            哈希表底層使用的也是數組機制,數組中也存放對象,而這些對象往數組中存放時的位置比較特殊,當需要把這些對象給數組中存放時,那麼會根據這些對象的特有數據結合相應的算法,計算出這個對象在數組中的位置,然後把這個對象存放在數組中。而這樣的數組就稱爲哈希數組,即就是哈希表。

            當向哈希表中存放元素時,需要根據元素的特有數據結合相應的算法,這個算法其實就是Object類中的hashCode方法。由於任何對象都是Object類的子類,所以任何對象有擁有這個方法。即就是在給哈希表中存放對象時,會調用對象的hashCode方法,算出對象在表中的存放位置,這裏需要注意,如果兩個對象hashCode方法算出結果一樣,這樣現象稱爲哈希衝突,這時會調用對象的equals方法,比較這兩個對象是不是同一個對象,如果equals方法返回的是true,那麼就不會把第二個對象存放在哈希表中,如果返回的是false,就會把這個值存放在哈希表中。

            總結:保證HashSet集合元素的唯一,其實就是根據對象的hashCode和equals方法來決定的。如果我們往集合中存放自定義的對象,那麼保證其唯一,就必須複寫hashCode和equals方法建立屬於當前對象的比較方式。

  •  HashSet存儲自定義類型元素

            給HashSet中存放自定義類型元素時,需要重寫對象中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的對象唯一

    publicclass Student {

        private String name;

        private int age;

        public Student(String name, int age) {

            super();

            this.name = name;

            this.age= age;

        }

        public String getName() {

            returnname;

        }

        public void setName(Stringname) {

            this.name= name;

        }

        public int getAge() {

            returnage;

        }

        public void setAge(int age) {

            this.age= age;

        }

        @Override

        public String toString() {

            return "Student [name=" + name + ",age=" + age+ "]";

        }

        @Override

        publicint hashCode() {

            final int prime = 31;

            int result = 1;

            result = prime * result + age;

            result = prime * result + ((name == null) ? 0 : name.hashCode());

            return result;

        }

        @Override

        publicbooleanequals(Object obj) {

            if (this == obj)

                return true;

            if(!(obj instanceof Student)){

                System.out.println("類型錯誤");

                returnfalse;

            }

            Student other = (Student) obj;

            return this.age == other.age && this.name.equals(other.name);

        }

    }

  • 判斷集合元素唯一的原理

    ArrayList的contains方法判斷元素是否重複原理

            ArrayList的contains方法會使用調用方法時,傳入的元素的equals方法依次與集合中的舊元素所比較,從而根據返回的布爾值判斷是否有重複元素。此時,當ArrayList存放自定義類型時,由於自定義類型在未重寫equals方法前,判斷是否重複的依據是地址值,所以如果想根據內容判斷是否爲重複元素,需要重寫元素的equals方法。


  • HashSet的add/contains等方法判斷元素是否重複原理

    Set集合不能存放重複元素,其添加方法在添加時會判斷是否有重複元素,有重複不添加,沒重複則添加。

    HashSet集合由於是無序的,其判斷唯一的依據是元素類型的hashCode與equals方法的返回結果。規則如下:

    先判斷新元素與集合內已經有的舊元素的HashCode值

     如果不同,說明是不同元素,添加到集合。

     如果相同,再判斷equals比較結果。返回true則相同元素;返回false則不同元素,添加到集合。

    所以,使用HashSet存儲自定義類型,如果沒有重寫該類的hashCode與equals方法,則判斷重複時,使用的是地址值,如果想通過內容比較元素是否相同,需要重寫該元素類的hashcode與equals方法。



發佈了70 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章