Java核心API -- 6(Collection集合List、Set、ArrayList、HashSet)

1. Collection集合框架

    Java.util.Collection接口

        |--List子接口

                |--ArrayList實現類

                |--LinkedList實現類

                |--Vector實現類

                        |--Stack(棧,繼承Vector,先進後出)

        |--Set子接口

                |--HashSet實現類

                |--TreeSet實現類

        |--Queue接口(普通隊列,先進先出)

                |--Deque子接口(雙端隊列)

                        |--ArrayDeque實現類


2. 泛型

    1)泛型是 JDK1.5引入的新特性,泛型的本質是參數化類型。在類、接口、方法的定義過程中,所操作的數據類型爲傳入的指定參數類型。所有的集合類型都帶有泛型參數,這樣在創建集合時可以指定放入集合中的對象類型。同時,編譯器會以此類型進行檢查。 

    2)ArrayList支持泛型,泛型尖括號裏的符號可隨便些,但通常大寫E。

    3)迭代器也支持泛型,但是迭代器使用的泛型應該和它所迭代的集合的泛型類型一致!

    4)泛型只支持引用類型,不支持基本類型,但可以使用對應的包裝類

    5)如果泛型不指定類型的話,默認爲Object類型。


    案例6:

        wKioL1WI0FazbcapAAGX6d8c_qw963.jpg


 

3. List接口和Set接口

     1)List接口:List接口是Collection的子接口,用於定義線性表數據結構,元素可重複、有序的;可以將List理解爲存放對象的數組,只不過其元素個數可以動態的增加或減少。 

        (1) List接口的兩個常見的實現類:ArrayList和LinkedList,分別用動態數組和鏈表的方式實現了List接口。List、ArrayList和LinkedList均處於java.util包下。

        (2) 可以認爲ArrayList和LinkedList的方法在邏輯上完全一樣,只是在性能上有一定的差別,ArrayList更適合於隨機訪問,而LinkedList更適合於插入和刪除,在性能要求不是特別苛刻的情形下可以忽略這個差別。

        (3) 使用List我們不需要在創建的時候考慮容量集合的容量是根據其所保存的元素決定的換句話說,集合的容量是可以自動擴充的。

        (4) List的實現類會重寫toString方法,依次調用所包含對象的toString方法,返回集合中所包含對象的字符串表現 。

    2)Set接口:Set接口是Collection的子接口,用於存儲不重複的元素,元素是無序的。

        (1) HashSet和TreeSet是Set集合的兩個常見的實現類,分別用hash表和排序二叉樹的方式實現了Set集合。HashSet是使用散列算法實現Set的。

        (2) Set集合沒有get(int index)方法,我們不能像使用List那樣,根據下標獲取元素。想獲取元素需要使用Iterator。

        (3) 向集合添加元素也使用add方法,但是add方法不是向集合末尾追加元素,因爲無序。

 

4. ArrayList實現類的常用方法

    (1) add(Object obj):向想集合末尾追加一個新元素,從該方法的參數定義不難看出,集合可以存放任意類型的元素,但在實際編程中我們發現,幾乎不會向集合中存放一種以上的不同類型的元素。

    (2) size()方法:返回當前集合中存放對象的數量。

    (3) clear()方法:用於清空集合。

    (4) isEmpty()方法:用於返回集合是否爲空。


    案例7:

        wKioL1WI0JjBtnUwAAGSTCghIlY317.jpg


     (5) contains(Object obj)方法:檢查給定對象是否被包含在集合中,檢查規則是將obj對象與集合中每個元素進行equals比較,若比對了所有元素均沒有equals爲true的則返回false。注意事項:根據情況重寫equals:若比較是否是同一個對象,則不需要重寫,直接用contains裏的equals比較即可。若重寫equals爲內容是否相同,則按內容比較,不管是否同一個對象。是否重寫元素的equals方法對集合的操作結果有很大的效果不同!

    (6) boolean remove(Object obj)方法:刪除一個元素,不重寫equals,不會有元素被刪除(因爲比較的是對象的地址,都不相同),重寫equals爲按內容比較,則刪除第一個匹配的就退出,其他即使內容相同也不會被刪除。


       wKiom1WIzv7DvppDAAFkLbn2iEc503.jpg


    (7) Object remove(int index)方法:移除此列表中指定位置上的元素。向左移動所有後續元素(將其索引減1)。因此在做刪除操作時集合的大小爲動態變化的,爲了防止漏刪,必須從後往前刪!


        wKiom1WIzyDAAtreAAEywALwbMs937.jpg


    (8) Object get(int index)方法:根據元素下標獲取對應位置的元素並返回。

    (9) Object set(int index,Object newElement)方法:將index位置的元素修改爲newElement,修改後將被修改的元素返回。可實現將List中第i個和第j個元素交換的功能:list.set ( i , list.set ( j , list.get ( i ) ) ) ;

    (10) add(int index,Object newElement)方法:使用add的重載方法,我們可以向index指定位置插入newElement,原位置的元素自動向後移動,即所謂的“插隊”。


        wKioL1WI0PezYuMhAAH17Xi-dHk227.jpg


    (11) Object[] toArray()方法:該方法繼承自Collection的方法,該方法會將集合以對象數組的形式返回。

    (12) List<E> subList(int fromIndex, int toIndex)方法:獲取子集合,但在獲取子集後,若對子集合的元素進行修改,則會影響原來的集合。


        wKiom1WIz2aDe3LCAAHrp_E1UDg984.jpg


 

5. HashSet實現類常用常用方法

    (1)  boolean add(E e) :如果此 set 中尚未包含指定元素,則添加指定元素。  

    (2) void clear() :從此 set 中移除所有元素。

    (3) Object clone() :返回此 HashSet 實例的淺表副本:並沒有複製這些元素本身。  

    (4) boolean contains(Object o) :如果此 set 包含指定元素,則返回 true。  

    (5) boolean isEmpty() :如果此 set 不包含任何元素,則返回 true。  

    (6) Iterator<E> iterator(): 返回對此 set 中元素進行迭代的迭代器。  

    (7) boolean remove(Object o): 如果指定元素存在於此 set 中,則將其移除。  

    (8) int size() :返回此 set 中的元素的數量(set 的容量)。  

    注意事項:

    1)hashCode對HashSet的影響:若我們不重寫hashCode,那麼使用的就是Object提供的,而該方法是返回地址(句柄)!換句話說,就是不同的對象,hashCode不同。

    2)對於重寫了equals方法的對象,強烈要求重寫繼承自Object類的hashCode方法的,因爲重寫hashCode方法與否會對集合操作有影響!

    3)重寫hashCode方法需要注意兩點:①與equals方法的一致性,即equals比較返回爲true的對象其hashCode方法返回值應該相同(優肯不同)。②hashCode返回的數值應該符合hash算法要求,如果有很多對象的hashCode方法返回值都相同,則會大大降低hash表的效率。一般情況下,可以使用IDE(如Eclipse)提供的工具自動生成hashCode方法。

    4)boolean contains(Object o)方法:查看對象是否在set中被包含。下例雖然有新創建的對象,但是通過散列算法找到了位置後,和裏面存放的元素進行equals比較爲true,所以依然認爲是被包含的(重寫equals了時)。

    5)HashCode方法和equals方法都重寫時對hashSet的影響:將兩個對象同時放入HashSet集合,發現存在,不再放入(不重複集)。當我們重寫了Point的equals方法和hashCode方法後,我們發現雖然p1和p2是兩個對象,但是當我們將他們同時放入集合時,p2對象並沒有被添加進集合。因爲p1在放入後,p2放入時根據p2的hashCode計算的位置相同,且p2與該位置的p1的equals比較爲true, hashSet認爲該對象已經存在,所以拒絕將p2存入集合。


    案例8:

        wKiom1WI1MGBIOMdAAIqIuNHFDw699.jpg


    6)不重寫hashCode方法,但是重寫了equals方法對hashSet的影響:兩個對象都可以放入HashStet集合中,因爲兩個對象具有不用的hashCode值,那麼當他們在放入集合時,通過hashCode值進行的散列算法結果就不同。那麼他們會被放入集合的不同位置,位置不相同,HashSet則認爲它們不同,所以他們可以全部被放入集合。 

    7)重寫了hashCode方法,但是不重寫equals方法對hashSet的影響:在hashCode相同的情況下,在存放元素時,他們會在相同的位置,hashSet會在相同位置上將後放入的對象與該位置其他對象一次進行equals比較,若不相同,則將其存入在同一個位置存入若干元素,這些元素會被放入一個鏈表中。由此可以看出,我們應該儘量使得多種類的不同對象的hashcode值不同,這樣纔可以提高HashSet在檢索元素時的效率,否則可能檢索效率還不如List。注意:兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code。

 

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