概念與作用
集合概念
現實生活中:很多事物湊在一起
數學中的集合:具有共同屬性的事物的總體
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()方法遍歷集合
-
迭代器:獲取集合迭代器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
將指定的值與此映射中的指定鍵關聯(可選操作)。如果此映射以前包含一個該鍵的映射關係,則用指定值替換舊值(當且僅當 m.containsKey(k) 返回 true 時,才能說映射 m 包含鍵 k 的映射關係)。
參數:
key - 與指定值關聯的鍵
value - 與指定鍵關聯的值
返回:
以前與 key 關聯的值,如果沒有針對 key 的映射關係,則返回 null。(如果該實現支持 null 值,則返回 null 也可能表示此映射以前將 null 與 key 關聯)。
Map接口提供三種方法:1.
Set<K> |
2.
Collection<V> |
values() 返回此映射中包含的值的 Collection 視圖。 |
3.
Set<Map.Entry<K,V>> |
HashMap類
案例功能
集合工具類:Collections
Collections 類是用於操作List、Set和Map等集合的工具類,該類提供了大量的方法可以對集合元素進行排序、查詢和修改等操作。
Collections 類是java.util包下的。它所提供的方法均爲靜態方法,可以直接通過“類名.方法”的形式調用。
小結
- 集合的長度是可變的,但是隻能存放引用數據類型的數據,不能存放基本數據類型的數據;
- Collection 是集合類的基本接口,其主要的子接口有List 和 Set。而Map 不是其子接口。Collection 接口聲明所有集合類的核心方法,一般情況下都不會使用Collection 接口,而是使用其子類List和Set集合。
- List 是有序的Collection,使用List 接口可以精確地控制每個元素插入的位置,也可以通過索引來訪問List集合中的元素。List接口常用的實現類有ArrayList 和LinkedList。List 集合允許存放重複的元素。
- Set 是一個不包含重複元素的Collection,Set允許包含null元素,但不能包含重複的元素。一般重寫類的equals() 和 hashCode() 方法來區別Set集合中元素是否相同。
- Set 接口常用的子類有HashSet 和TreeSet,其中HashSet 是按照哈希算法來存取集合中的元素的,其存取的效率高。HashSet 類是無序存放元素的,而TreeSet 是有序存放元素的,但是需要使用Comparable 進行排序操作。
- 集合的輸出有多種方式,其中使用Iterator 迭代器是標準的輸出方式,在JDK1.5 之後集合也支持了foreach 方式。
- Map 沒有繼承Collection 接口,可以用於保存具有映射關係的數據,其提供的是key 到value的映射。
- Map接口常用實現類有HashMap 和TreeMap。HashMap 類是基於哈希表的Map接口的實現,對於元素的添加和刪除有着較高的效率。TreeMap 集合主要是對所有的key進行排序,從而保證所有的key-value 映射關係處於有序狀態。TreeMap 集合在元素的添加、刪除和定位映射性能較低。