一、集合和數組的區別
1. 數組:
(1) 長度不可變
(2) 可以是任意類型
2. 集合
(2) 長度可變
(3) 引用類型
二、集合的關係結構
列出了最常使用的集合接口和實現類的關係。
三、java.util.Collection:接口
單列集合的根接口,裏面定義的方法,子接口和實現類都有。
常用方法
public boolean add(E e)
: 把給定的對象添加到當前集合中 。public boolean contains(Object obj)
: 判斷當前集合中是否包含給定的對象。public boolean isEmpty()
: 判斷當前集合是否爲空。public int size()
: 返回集合中元素的個數。public boolean remove(E e)
: 把給定的對象在當前集合中刪除。public Object[] toArray()
: 把集合中的元素,存儲到數組中public void clear()
:清空集合中所有的元素。
- 注意事項:
- Collection中沒有定義索引,因爲List有索引,而Set是沒有索引的,索引僅僅是List接口的特性。
- toArray方法返回的是Object數組,需要強制類型轉換調用子類特有方法
解決:使用迭代的方法
-
並不是所有的集合都有索引,以前使用for+get方法索引,沒了索引就不行了。jdk提供了一中遍歷集合的通用方式那就是使用迭代器
java.util.Iterator<E>
tip: 詳細方法使用和其他方法詳見API文檔學習。
四、java.util.List:接口
繼承自java.util.Collection
接口
1、特點
- 保證存入元素一次進來的順序
- 有索引,實現類可以通過成員方法
get(int index)
訪問指定位置的元素 - 存入的元素可重複
2、常用方法
List繼承了Collection集合的全部方法,同時還有自己的特有方法
- 特有方法:
public void add(int index, E element)
: 將指定的元素,添加到該集合中的指定位置上。public E get(int index)
:返回集合中指定位置的元素。public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。public E set(int index, E element)
:用指定元素替換集合中指定位置的元素,返回值的更新前的元素
3、實現類
1、java.util.ArrayList
(1)底層原理
-
底層是數組實現
a.每次先開闢一個定長爲10的數組空間
b.如果空間不夠,在開闢一個1.5倍原本長度+1的數組空間,c.把當前數組拷貝進去,最後銷燬原本的數組
d.並且讓集合對象指向新的數組。 -
刪除元素的原理:
a.查找元素是否存在
b.存在,記錄索引
c.創建一個新數組
d.把剩餘元素拷貝進入新數組
e.數組變量指向新的數組地址
f.銷燬老數組所佔的內存空間
(2)特點
- 查詢速度快,增刪快
- 底層是數組結構
- 查詢快的原因:有索引,元素內存分佈連續
- 線程不同步–不安全–效率高
(3)拓展瞭解
`java.util.Vector<E>:`(基本已經不用)
1.底層也是數組結構
2.線程同步--安全--但是效率低下
2、java.util.LinkedList
(1)特點
- 查詢慢,增刪快
- 底層是鏈表結構
- 線程不同步–不安全–效率高
(2)特有方法
-
void addFirst(E e)
在該列表開頭插入指定的元素。 -
void addLast(E e)
將指定的元素追加到此列表的末尾。 -
E getFirst()
返回此列表中的第一個元素。 -
E getLast()
返回此列表中的最後一個元素。 -
E removeFirst()
從此列表中刪除並返回第一個元素。 -
E removeLast()
從此列表中刪除並返回最後一個元素。 -
LinkedList
集合中,具有棧結構特點(先進後出)的方法
public E pop()
從此列表表示的堆棧中彈出一個元素。
public void push(E e)
將元素推送到由此列表表示的堆棧上。
五、 java.util.Set:接口
繼承自java.util.Collection
接口
1、特點
- 無索引
- 集合內元素唯一
2、常用實現類
(1)java.util.HashSet
特點
- 無索引
- 集合內元素唯一
- 不保證存入和取出的順序是一致的
- 底層數據結構:哈希表——數組 + 鏈表(節點數>8–紅黑樹)
(2)java.util.LinkedHashSet
特點
- 無索引
- 集合內元素唯一
- 存入和取出是有序的
- 底層數據結構:哈希表 + 鏈表
哈希表:保證數據的唯一(同HashSet)
鏈表:保證數據是有序的
3、集合內部保證元素唯一性的原理
根本原因:java.lang.Object
類中帶有hashCode
方法。
hashCode
方法
- 返回該對象的哈希碼值(int類型)
- Object的
hashCode
方法,根據對象的地址值計算出一個int數字,叫做哈希碼值(哈希地址值) - 所以只要new對象,就會產生新的地址,因此哈希值也就不同
注意事項:
- 子類不重寫hashCode方法,調用Object類的hashCode方法,根據對象地址值計算哈希值。
- 子類根據地址值計算哈希值沒有意義,需要根據內容計算哈希值。
- 由於new對象,就會產生新的地址,因此哈希值也就不同,自定義類要實現存入Set集合保證唯一就必須要重寫
hashCode
方法和equals
方法。 - 根據String的代碼測試,發現String覆蓋重寫hashCode方法,重寫方式:根據String中每個字符的ASCII碼值通過一個算法進行相加的出哈希值。只要是算法就會存在缺陷。
出現內容不同哈希值相同的情況
System.out.println("重地".hashCode()); // 1179395
System.out.println("通話".hashCode()); // 1179395
總結–根據內容計算哈希值:
- 哈希值不同內容一定不相同
- 哈希值相同,內容可能不相同,因此還需要調用equeals方法進行內容的判斷。
爲什麼需要hashCode方法?
爲了在使用哈希表的時候能減少equals方法的調用,提高效率。
4、hashSet存儲元素的原理(重點!)
(1)哈希表結構圖
(2)HashSet存儲原理流程圖
(3)實例流程圖
注:
【1】加載因子:說明什麼時候數組(table)進行擴容,0.75說明數組(table)的使用比例大於0.75就進行擴容,擴容爲原來的2倍。
總結
Set
集合接口所有實現類保證元素唯一:依賴於hashCode
方法和equals
方法。
存入Set
集合的元素要保證唯一必須覆寫hashCode
方法和equals
方法。
六、List與Set的轉換
- List與Set接口的實現類都有方法:
boolean addAll(Collection<? extends E> c)
可以實現兩種接口集合的轉換。 - List與Set接口的實現類都有構方法:
ArrayList(Collection<? extends E> c)
、LinkedList(Collection<? extends E> c)
、HashSet(Collection<? extends E> c)和LinkedHashSet(Collection<? extends E> c)可以實現兩種接口類型的轉換。
使用場景:
需求一:
要求把List集合中元素去重
1.按順序
2.不按順序
解決方案:
- 四種方法:
1、新建一個列表,元素依次加入並使用contains()
方法判斷是否已經存在,新數組中不存在就加入,存在就捨棄。
2、List
數據一個個加入到Set
中
3、Set直接用addAll(Collection< E> c)
4、Set構造方法Set(Collection< E> c)
需求二:
要求把Set集合按從小到大排序
分析與解決方案
我們知道Set集合是沒有sort方法的,並且Collections工具類中的sort方法也是支持List接口的實現子類。
由於List的構造方法可以接受的是Collection c 參數,所以也可以把Set轉換成List,之後使用collections工具類排序
七、集合工具類:java.util.Collections
- 特點
- 構造方法私有
- 全部是靜態方法
- 常用方法:
public static void addAll(List<?> list,T ... elements)
:把元素集合加入到指定集合listpublic static void shuffle(List<?> list)
:打亂集合內元素pubiic static <T> void sort(List<T> list,comparator<? super T> comp)
:把指定集合進行排序(可自定義排序)