# finally -> 02 【Collection、泛型】
## 1.集合
### 1.1集合與數組
##### 集合的概述:
1. 數組是一種容器,集合也是一種容器,都可以存放多個數據。
2. 數組的長度一旦確定,運行期間不可改變;但是大多數集合的長度可以變化。
3. 曾經已經學習過的ArrayList類,只是多種集合當中的一種而已。
4. 數組當中的數據類型必須統一,但是集合當中的元素“可選統一”。
創建集合的時候,可以寫一個泛型<>,代表集合當中統一的數據類型是什么。
如果集合創建的時候,沒有寫<>,那么所有數據類型都可以放進來,都將會處理成為Object。
### 1.2 Collection接口常用方法
java.util.Collection接口當中規定的常用集合方法有:
public boolean add(E e):把指定的參數元素,添加到集合中;返回添加動作是否成功。
public boolean remove(Object e):根據參數指定的元素內容,從集合當中刪除元素;返回刪除是否成功。
public boolean contains(Object e):判斷集合是否包含指定的元素。
public boolean isEmpty():判斷集合是否為空白(一個元素都沒有)。
public void clear():清空集合當中所有的元素內容。
public int size():獲取集合的長度尺寸。
public Object[] toArray():將集合轉換成為數組形式。
##### `注意事項`:
對于remove方法和contains方法來說,參數是Object類型。這里是如何得知兩個對象是否“相同”的呢?由equals和hashCode兩個方法共同決定。
### 1.3迭代器
并不是所有的集合都有索引值,所以對于Collection接口來說,普通的for循環索引i那種方式不一定適用。
有一個叫做“迭代器”的小東東,非常好用,專門用來遍歷集合的。無論是什么集合,只要是Collection的實現類,都可以用。
##### `使用步驟:`
1. 根據集合獲取一個對應的迭代器(注意不是自己new的,而是從集合當中獲取的。)
2. 通過迭代器,看看有沒有下一個。
3. 如果有下一個,通過迭代器獲取下一個,并且向后移動一個位置。
4. 上述2-3步驟是一個循環,直到沒有下一個為止。(while循環。)
java.util.Iterator<T>接口代表迭代器,其中有兩個常用的方法:
boolean hasNext():`判斷有沒有下一個元素``
T next():獲取下一個,并且向后移動一個位置
##### 注意:
在使用迭代器遍歷集合的過程當中,一定要避免直接通過集合改變其中元素的個數。否則就會導致ConcurrentModificationException并發修改異常。
### 1.4增強for循環
增強for循環(昵稱也叫做for-each循環)是JDK 1.5添加的特性之一。
for (數據類型 變量名稱 : 數組) {
// ...
}
其中的數據類型并不一定是int,不代表索引值。
含義:用左邊的變量,分別得到右側數組當中的每一個數據值。
##### 備注:
這其實只是一個語法糖。對于數組來說,增強for循環底層其實就是一個普通的for循環。
增強for循環照樣也可以支持集合。
for (數據類型 變量名稱 : 集合) {
// ...
}
##### 備注:
這其實也是一種語法糖,對于集合來說,底層其實就是迭代器,只是表面上增強for循環的寫法簡單而已。
##### 在使用增強for循環的時候,注意事項:
1. 支持數組,其實是一個語法糖,底層就是普通的fori循環。
2. 支持java.lang.Iterable接口對象,其中就包含了集合。因為這個接口規定了一項能力:
public Iterator<T> iterator():獲取迭代器的方法。
3. 支持集合,也是一個語法糖。底層就是在使用迭代器。
4. 增強for循環當中沒有索引值,所以就無法直接修改數組或集合中的內容。【重點】
`基本數據類型存儲的就是數據值`,
`引用數據類型存儲的是地址值`。
##### 備注:
集合當中保存的其實都是對象的【地址值】。
增強for循環沒有索引值,所以基本數據類型的數據值不能變,同時引用數據類型的地址值不能變
## 2.泛型
### 2.1泛型概述
##### 使用泛型的好處:
1. 保證類型統一,確保類型安全。
2. 將可能發生的類型安全問題,從運行期提前到編譯期。(有問題盡量在javac的時候就暴露出來最好,別等到java運行時再暴露)
3. 省去向下轉型的麻煩。
4. 讓代碼模板化。
##### `自定義泛型的三種用法`:
1. 泛型類
2. 泛型接口
3. 泛型方法
### 2.2泛型類定義
自定義一個泛型類
修飾符 class 類名稱<泛型> {
// ...
}
泛型的名稱用什么都可以,一般推薦使用大寫字母。
泛型代表一種尚不確定的類型,所有本類范圍之內都能用這個泛型當做不確定的類型進行使用。
什么時候才能確定這個泛型?
當創建泛型類對象的時候,就可以確定。
##### 定義一個泛型接口
修飾符 interface 接口名稱<泛型> {
// ...
}
含義和泛型類是完全相同的:本接口之內泛型通用。
##### `時候確定接口的泛型`
1. 實現類在實現接口的時候,直接指定具體泛型。
2. 實現類仍然不指定具體泛型,那么實現類也必須是一個泛型類。
##### 注意:
對于泛型類/泛型接口來說,泛型是在本類/本接口當中全局通用。
##### `泛型方法的格式:`
修飾符 <泛型> 返回值類型 方法名稱(參數類型 參數名稱) {
方法體
}
##### 備注:
這個泛型定義在方法上,所以只有當前這個方法自己專用。別人不能用。
### 2.3泛型的通配符
泛型的通配符其實就是一個問號:【?】
作用:用來被動匹配任何一種泛型。
##### 注意事項:
1. 一旦使用了泛型?通配符進行匹配接收,那么遍歷的時候就只能當做Object,因為不確定泛型到底傳進來的是誰。
2. 這個通配符問號,只能在匹配接收的時候使用,不能在定義泛型的時候使用。
對于泛型的通配符問號,有兩種特殊寫法:
##### 上下限,上下界。
##### <?>:隨便,誰都行。
<? extends 類>:可以是指定的類,或者其子類。(上限,最高不能超過這個類。)
<? super 類>:可以是指定的類,或者其父類。(下限,最低不能超過這個類。)