1. 程式人生 > >Java集合框架(比較囉嗦)

Java集合框架(比較囉嗦)

閱讀目錄

概念與作用

集合概念

現實生活中:很多事物湊在一起

數學中的集合:具有共同屬性的事物的總體

java中的集合類:是一種工具類,就像是容器,儲存任意數量的具有共同屬性的物件

 在程式設計時,常常需要集中存放多個數據,當然我們可以使用陣列來儲存多個物件。但陣列長度不可變化,一旦初始化陣列時指定了陣列長度,則這個陣列長度是不可變的,如果需要儲存個數變化的資料,陣列就有點無能為力了;而且陣列無法儲存具有對映關係的資料,如成績表:語文-79,數學-80,這種資料看上去像兩個陣列,但這個兩個陣列元素之間有一定的關聯關係。

        為了儲存數量不確定的資料,以及儲存具有對映關係的資料(也被稱為關聯陣列),java提供集合類。集合類主要負責儲存、盛裝其他資料,因此集合類也被稱為容器類。所有集合類都位於java.util包下。

        集合類和陣列不一樣,陣列元素既可以是基本型別的值,也可以是物件(實際上儲存的是物件的引用變數);而集合裡只能儲存物件(實際上也是儲存物件的引用變數,但通常習慣上認為集合裡儲存的是物件)。     

 

集合的作用

集合與陣列對比

回到頂部

集合框架的體系結構

Java的集合類主要由兩個介面派生而出:Collection和Map,

Collection和Map是Java集合框架的根介面,這兩個介面又包含了一些子介面或實現類。

圖7.1是Collection介面、子介面及其實現類的繼承樹。

  圖7.1中的粗線圈出的Set和List介面是Collection介面派生出的兩個子介面,它們分別代表了無序集合和有序集合,陰影部分HashSet和ArrayList是兩個主要的實現類。

 圖7.2是Map體系的繼承數,所有的Map實現類用於儲存具有對映關係的資料(也就是前面介紹的關係陣列)

   圖7.2中顯示了Map介面的眾多實現類,這些實現類在功能、用法上存在一定的差異,但它們都有一個功能特徵:Map儲存的每項資料都是Key-value對,也就是有key和value兩個值組成。就像前面介紹的成績單:語文-79,數學-80,每項成績都由2個值組成。Map裡的key是不可重複的,key用於標識集合裡每項資料,如果需要查閱Map中資料時,總是根據Map的key來獲取。

 根據圖7.1和圖7.2中粗線標識的3個介面,我們可以把java的所有集合分成三大類:其中Set集合類似於一個罐子,把一個物件新增到Set集合時,Set集合無法記住這個元素的順序,所以Set裡的元素不能重複(否則系統無法準確識別這個元素);List集合非常像一個數組,它可以記住每次新增元素的順序,只是List的長度是可變的。Map集合也像一個罐子,只是它裡面的每項資料都由兩個值組成。

  如果訪問List集合中的元素,可以直接根據元素的索引來訪問;如果需要訪問Map集合中的元素,可以根據每項元素的key來訪問其value;如果希望訪問Set集合中的元素,則只能根據元素本身來訪問(這也是Set集合裡元素不允許重複的原因)。

 對於List、Set和Map三種集合,最常用的實現類在圖7.1、7.2中以灰色區域覆蓋,分別是HashSet、ArrayList和HashMap三個實現類。

回到頂部

Collection介面和List介面簡介

List介面是一個有序集合,其元素以線性方法儲存,集合中允許存放重複的元素。

List介面及其實現類——ArrayList

ArrayList 類是陣列列表類,實現了可變長度的陣列,允許對集合中的元素進行快速的訪問,但向ArrayList 集合中插入或刪除速度較慢。。(需要移動元素)

ArrayList 集合允許所有的元素,包括null。

每一個ArrayList 例項都有一個預設的容量,即儲存元素的個數,這個容量可以隨著元素的增加而自動變大。

連結串列類:LinkedList類 

LinkedList 是連結串列類,採用連結串列結構儲存元素。連結串列結構的優點是便於向集合中插入和刪除元素。

因為在插入或刪除元素時,不需要移動任何元素。

List的增刪改查的方法

實現功能

建立Course類

真正工程中應將所有的屬性私有化,通過get和set方法去訪問屬性

建立學生類

學生能選課,就有很多課程資訊,把他的課程資訊存放在set型別的屬性courses裡

因為Set是一個介面,所以不能直接例項化,通過HashSet這個實現類來進行例項化。

建立一個備選課程類ListTest類

建立List型別的屬性courseToselect(用於存放備選課程的List)

新增ListTest構造方法,並初始化courseToselect屬性,因為List是一個介面,所以在構造方法中不能直接例項化,而通過它的實現類ArrayList來例項化。

物件存入集合當中的時候都會變成Object型別,取出時需要進行型別轉換
如果新增到List中的長度大於他目前的長度,則系統會出現異常,即陣列下表越界異常。
List是介面,所以在構造方法中不能直接例項化,而通過ArrayList例項化。

用ArrayList的addall方法時,需要將新增的資料轉換為列表型別,用asList方法。Arrays.asList(a) 將a由資料型別轉變為列表型別list。
用List的add(Object e)和add(int index,Object e)可以向List中新增單個元素,用addall(Collextion c)和addall(int index,Collextion c)可以新增集合(多個元素)。若在index位置有元素,則此元素及後面的元素向下移動。

用List的add(Object e)和add(int index,Object e)可以想List中新增單個元素,用addall(Collextion c)和addall(int index,Collextion c)可以新增集合(多個元素),

通過get()方法,可以把List中相應的索引位置上的元素給取出來。那麼如果想要取得List中每一個元素的值,需要用一個for迴圈像遍歷陣列一樣遍歷List。

建立一個testGet方法,為依次遍歷List中的元素,首先我們需要取得List的長度,通過呼叫List的Size()方法來實現。

1.用for迴圈配合get()方法遍歷集合

  1. 迭代器:獲取集合迭代器lt--while(lt.hasNext())迴圈遍歷集合--將lt.Next()強轉成集合元素型別並用其接收。注意:迭代器只遍歷不儲存,必須依賴集合存在。

    Iterator本身也是一個介面,Iterator介面。有一個hasNext方法(引數布林型別)

foreach迴圈遍歷:for(object obj:集合名)

修改List中的元素

List中有個set方法

set(int index, E element)方法,修改列表中的元素
引數:index - 要替換的元素的索引,element - 要在指定位置儲存的元素

返回:以前在指定位置的元素

刪除List中的元素

remove(Object e)

remove(int index)

removeAll()

泛型

建立一個TestGeneric類(測試泛型)

新增一個帶有泛型的List型別的屬性。在構造器中初始化courses屬性

測試迴圈遍歷,用for(Course cr: courses)

是把元素作為Course型別取出來,而不是作為Object型別取出來

泛型集合不僅可以存入泛型型別的物件例項,還可以新增泛型的子型別的物件例項

新建一個繼承Course類的ChildCourse類。Course類如果只有含參構造器的話,編譯器就不會自動新增隱式的無參構造器。子類中必須呼叫父類的隱式構造器ChildCourse類就會報錯。需要手動的在父類中加一個無參構造器。

在TestGeneric類中新增一個testChild方法

泛型集合可以新增泛型的子型別的物件例項

泛型集合中,不能新增泛型規定的型別及其子型別以外的物件,否則會報錯。

泛型應該注意的地方:
1.泛型集合中的限定型別不能使用基本資料型別。必須是引用資料型別。
2.如果非要使用基本資料型別時,必須使用它們的包裝類 如:int->Integer

Set

Set介面及其實現類--HashSet

list有序的,Set無序的 ,所以Set沒有set()這個給定指定索引位置去修改元素的方法。

案例功能

建立一個SetTest類

將Student類中Set型別的屬性修改一下,新增一個Course型別的泛型。

在SetTest類新增一個帶有泛型Course的List型別的屬性courseToSelect,建立SetTest的構造器,初始化courseToSelect屬性

因為課程的ID是一個字串,是一個物件,用equals方法跟輸入的字串比較是否相等。

set特點:無序,不可重複

無序:迴圈遍歷set時只能用foreach或者迭代器iterator方法,不能用get()方法,因為set是無序的,沒有index。遍歷輸出也是亂序的。

不可重複:如果新增幾個相同的元素,則只會保留一個!

雜湊級:HashSet 類 

HashSet類是按照雜湊演算法來存取集合中的元素的,使用雜湊演算法可以提高存取的效率。當向HashSet 集合中新增元素時,就會呼叫該元素的hashCode() 方法,獲取雜湊碼值,然後根據這個雜湊碼值計算出該元素的存放位置。

HashSet 集合具有以下特點:

  • 不能保證元素的排列順序,集合中元素的順序隨時有可能發生改變。
  • 集合中最多允許存在一個null元素
  • HashSet 集合不是執行緒同步的。

Map和HashMap簡介

Collection儲存的都是單個元素。而Map提供了一種對映的關係(key到value的對映)。

因此,Map集合中儲存這兩組值,一組用於儲存key,另一組用於儲存value,key和value都可以是任何引用資料型別。Map集合中的key不允許重複,每一個key只能對映一個value。

 

Map介面

通過put()方法新增一個鍵值對的對映

put

V put(K key, V value)

將指定的值與此對映中的指定鍵關聯(可選操作)。如果此對映以前包含一個該鍵的對映關係,則用指定值替換舊值(當且僅當 m.containsKey(k) 返回 true 時,才能說對映 m 包含鍵 k 的對映關係)。

引數:

key - 與指定值關聯的鍵

value - 與指定鍵關聯的值

返回:

以前與 key 關聯的值,如果沒有針對 key 的對映關係,則返回 null。(如果該實現支援 null 值,則返回 null 也可能表示此對映以前將 null 與 key 關聯)。

Map介面提供三種方法:1.

Set<K>

keySet() 返回此對映中包含的鍵的 Set 檢視。

2.

Collection<V>

values() 返回此對映中包含的值的 Collection 檢視。

3.

 Set<Map.Entry<K,V>>

entrySet() 返回此對映中包含的對映關係的 Set 檢視。

HashMap類

案例功能

集合工具類:Collections

Collections 類是用於操作List、Set和Map等集合的工具類,該類提供了大量的方法可以對集合元素進行排序、查詢和修改等操作。

Collections 類是java.util包下的。它所提供的方法均為靜態方法,可以直接通過“類名.方法”的形式呼叫。

小結

  1. 集合的長度是可變的,但是隻能存放引用資料型別的資料,不能存放基本資料型別的資料;
  2. Collection 是集合類的基本介面,其主要的子介面有List 和 Set。而Map 不是其子介面。Collection 介面宣告所有集合類的核心方法,一般情況下都不會使用Collection 介面,而是使用其子類List和Set集合。
  3. List 是有序的Collection,使用List 介面可以精確地控制每個元素插入的位置,也可以通過索引來訪問List集合中的元素。List介面常用的實現類有ArrayList 和LinkedList。List 集合允許存放重複的元素。
  4. Set 是一個不包含重複元素的Collection,Set允許包含null元素,但不能包含重複的元素。一般重寫類的equals() 和 hashCode() 方法來區別Set集合中元素是否相同。
  5. Set 介面常用的子類有HashSet 和TreeSet,其中HashSet 是按照雜湊演算法來存取集合中的元素的,其存取的效率高。HashSet 類是無序存放元素的,而TreeSet 是有序存放元素的,但是需要使用Comparable 進行排序操作。
  6. 集合的輸出有多種方式,其中使用Iterator 迭代器是標準的輸出方式,在JDK1.5 之後集合也支援了foreach 方式。
  7. Map 沒有繼承Collection 介面,可以用於儲存具有對映關係的資料,其提供的是key 到value的對映。
  8. Map介面常用實現類有HashMap 和TreeMap。HashMap 類是基於雜湊表的Map介面的實現,對於元素的新增和刪除有著較高的效率。TreeMap 集合主要是對所有的key進行排序,從而保證所有的key-value 對映關係處於有序狀態。TreeMap 集合在元素的新增、刪除和定位對映效能較低。