Collection
|--List
|--ArrayList
|--Vector
|--LinkedList
|--Set
|--HashSet
|--TreeSet
集合和數組的區別
A:長度區別
數組的長度固定
集合長度可變
B:內容不同
數組存儲的是同一種類型的元素
而集合可以存儲不同類型的元素
C:元素的數據類型問題
數組可以存儲基本數據類型,也可以存儲引用數據類型
集合只能存儲引用類型
數組有沒有length()方法,字符串有沒有length()方法。集合有沒有length()方法;
沒有,有,沒有
迭代器集合的專門遍歷方式
Iterator iterator():迭代器,集合的專用遍歷方式
while (it.hasNext()) {
System.out.println(it.next());
}
用for循環改寫效率高,因為用Iterator之后就是垃圾了。
for(Iterator it;it.hasNext();){
System.out.println(it.next());
}
迭代器為什么是接口,而不是一個類。
假設迭代器定義的是一個類,這樣我們就可以創建該類的對象,調用該類的方法來實現集合的遍歷。
由于Java提供了很多的集合類,而這些集合類的數據結構是不同的。所以,存儲的方式和遍歷的方式應該是不同的。進而遍歷方式也應該不一樣,最終沒有定義迭代器類的。
而無論你是哪種集合,你都應該具備獲取元素的操作,并且,最好在輔助于判斷功能,這樣,在獲取前,先判斷,這樣就更不容易出錯,也就是說,判斷功能和獲取功能應該是一個集合遍歷所具備的,而每種集合的方式又不太一樣,所以我們把這兩個功能給提取出來,并不提供具體實現,這種方式就是接口。
那么,真正的具體的實現類在哪里呢?
在真正的具體的子類中,以內部類的方式體現的。
(增強for就是用來替代迭代器的)
List集合
- 有序:進去的時候是什么順序出去也是什么順序(并不是排序)
- 允許重復的元素;
list集合的特有遍歷功能
size()方法和get()方法結合使用用for循環
list集合的特有迭代器列表迭代器listIterator
listIterator繼承于Iterator接口
- 特有功能1 previous().往回走。獲取前一個元素
- hasPrevious(),判斷是否有元素
- 3.add()將指定元素添加。如果我們用Iterator去添加元素會出現并發修改異常。
數組
存儲同一種類型的多個元素的容器,有索引,方便我們獲取。
查詢快,增刪慢
鏈表
由一個鏈子把多個結點連起組成的數據
結點:有數據和地址組成(數據域和指針域組成)
查詢慢,增刪快
List子類的特點
- ArrayList:
底層數據結構是數組,查詢快,增刪慢。
線程不安全,效率高 - Vector:
底層數據結構是數組,查詢快,增刪慢。
線程安全,效率低 - LinkedList:
底層數據結構是鏈表,查詢慢,增刪快。
線程不安全,效率高
Vector的特有功能
因為Vector是1.0出現,在1.2版本才加入到list集合中,所以它有自己的特有功能。
addElement---add
elementAt----get
elements----iterator
JDK升級的原因:A,安全。B.效率。C.簡化書寫
LinkedList的特有功能
A:addFirst()/addLast()
B:getFirst()/getLast()
C:removeFirst()/removeLast()
contains()
contains()方法的底層是依賴equals()方法。當我們比較一個集合是否包含另一個集合的時候如果存儲的對象沒有重寫equals方法時,它就默認用的Object類中的方法,比較的是地址值。
asList(T...a)把數組轉換成集合
其本質還是數組,所以長度不能改變。集合的增加,刪除就會報錯。修改則可以。
Set
無序:存儲順序和取出順序不一致,(雖然)
唯一
HashSet
它不保證set的迭代順序,特別是不保證該順序恒久不變。
底層是HashMap保證hashset唯一,因為調用add就是hashmap的put()方法
通過add方法的源碼我們可以知道底層依賴的判斷兩個方法就是:hashCode()和equals()
- 步驟:
- 首先比較哈希值:如果相同繼續走,比較地址值或者走equals()
- 如果不同:就直接添加到集合中
如果類中沒有重寫這兩個方法,默認使用的是Object(),一般來說不同
而String類重寫了這兩個方法,所以內容相同就添加不進去。只添加一個
哈希表
是一個元素為鏈表的數組。綜合了數組和鏈表的好處。(好比如新華字典)
LinkedHahSet
底層數據結構由哈希表和鏈表組成。哈希表保證元素唯一性,鏈表保證元素有序(存儲和取出一致)
具有可預知的迭代順序
TreeSet
能夠對元素按照某種規則進行排序(自然排序,比較器排序)
特點:排序和唯一
- 唯一性:根據比較的返回是否是0來決定
- 排序:
- 自然排序(元素具備比較性):讓元素所屬的類實現自然排序的接口Comparable
- 比較器排序(集合具備比較性):讓集合的構造方法比較器接口的子類對象Comparator
底層數據結構是紅黑樹(紅黑樹是一種自平衡的二叉樹)保證元素的排序和唯一性。
自然排序
如果一個類的元素要想能夠進行自然排序,就必須實現自然排序接口Comparable<Student>,重寫方法
//按照姓名的長度排序
@Override
public int compareTo(Student s) {
// 主要條件 姓名的長度
int num = this.name.length() - s.name.length();
// 姓名的長度相同,不代表姓名的內容相同
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
// 姓名的長度和內容相同,不代表年齡相同,所以還得繼續判斷年齡
int num3 = num2 == 0 ? this.age - s.age : num2;
return num3;
}
比較器排序
第二個構造器需要我們傳入一個參數就是比較器對象,自定義一個類重寫方法:
new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 姓名長度
int num = s1.getName().length() - s2.getName().length();
// 姓名內容
int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
: num;
// 年齡
int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
return num3;
}
}
Map
將鍵映射到值得對象,一個映射不能包含重復的鍵,每個鍵最多只能映射到一個值。
- Map集合的數據結構值針對鍵有效,跟值無關
- Collection集合的數據結構是針對元素有效
map集合的遍歷
根據丈夫找妻子
獲取所有的鍵
遍歷鍵的集合,獲取每一鍵
-
根據去找值
// 獲取所有的鍵 Set<String> set = map.keySet(); // 遍歷鍵的集合,獲取得到每一個鍵 for (String key : set) { // 根據鍵去找值 String value = map.get(key); System.out.println(key + "---" + value); }
根據結婚證找丈夫和妻子
獲取所有鍵值對對象的集合
遍歷鍵值對對象的集合得到每一個鍵值對對象
根據鍵值對對象獲取鍵和值
// 獲取所有鍵值對對象的集合
Set<Map.Entry<String, String>> set = map.entrySet();
// 遍歷鍵值對對象的集合,得到每一個鍵值對對象
for (Map.Entry<String, String> me : set) {
// 根據鍵值對對象獲取鍵和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key + "---" + value);
}
HashMap
鍵是哈希表結構,可以保證鍵的唯一性(hashCode()和equals())
LinkedHashMap
Map接口的哈希表和鏈表列表實現,具有可預知的迭代順序
- 哈希表保證唯一性
- 鏈表保證有序(存儲和取出順序一致)
TreeMap
- 鍵是紅黑樹結構,可以保證鍵的排序(默認自然排序)和唯一性.
- 排序的話如果是自定義對象也得重寫Comparable接口,否則會報錯
HashMap和Hashtable(這里的't'是小寫)的區別
Hashtable:線程安全,效率低。不允許null建和null值
HashMap:線程不安全,效率高,允許null建和null值
Collections接口
是針對集合進行操作的工具類
Collection和Collections的區別
- :Collection 是單列集合的頂層接口,有兩個子接口List和Set
- :Collections 是針對集合進行操作的工具類,可以對集合進行排序和查找等
總結
-
:集合
Collection(單列集合) List(有序,可重復) ArrayList 底層數據結構是數組,查詢快,增刪慢 線程不安全,效率高 Vector 底層數據結構是數組,查詢快,增刪慢 線程安全,效率低 LinkedList 底層數據結構是鏈表,查詢慢,增刪快 線程不安全,效率高 Set(無序,唯一) HashSet 底層數據結構是哈希表。 哈希表依賴兩個方法:hashCode()和equals() 執行順序: 首先判斷hashCode()值是否相同 是:繼續執行equals(),看其返回值 是true:說明元素重復,不添加 是false:就直接添加到集合 否:就直接添加到集合 最終: 自動生成hashCode()和equals()即可 LinkedHashSet 底層數據結構由鏈表和哈希表組成。 由鏈表保證元素有序。 由哈希表保證元素唯一。 TreeSet 底層數據結構是紅黑樹。(是一種自平衡的二叉樹) 如何保證元素唯一性呢? 根據比較的返回值是否是0來決定 如何保證元素的排序呢? 兩種方式 自然排序(元素具備比較性) 讓元素所屬的類實現Comparable接口 比較器排序(集合具備比較性) 讓集合接收一個Comparator的實現類對象 Map(雙列集合) A:Map集合的數據結構僅僅針對鍵有效,與值無關。 B:存儲的是鍵值對形式的元素,鍵唯一,值可重復。 HashMap 底層數據結構是哈希表。線程不安全,效率高 哈希表依賴兩個方法:hashCode()和equals() 執行順序: 首先判斷hashCode()值是否相同 是:繼續執行equals(),看其返回值 是true:說明元素重復,不添加 是false:就直接添加到集合 否:就直接添加到集合 最終: 自動生成hashCode()和equals()即可 LinkedHashMap 底層數據結構由鏈表和哈希表組成。 由鏈表保證元素有序。 由哈希表保證元素唯一。 Hashtable 底層數據結構是哈希表。線程安全,效率低 哈希表依賴兩個方法:hashCode()和equals() 執行順序: 首先判斷hashCode()值是否相同 是:繼續執行equals(),看其返回值 是true:說明元素重復,不添加 是false:就直接添加到集合 否:就直接添加到集合 最終: 自動生成hashCode()和equals()即可 TreeMap 底層數據結構是紅黑樹。(是一種自平衡的二叉樹) 如何保證元素唯一性呢? 根據比較的返回值是否是0來決定 如何保證元素的排序呢? 兩種方式 自然排序(元素具備比較性) 讓元素所屬的類實現Comparable接口 比較器排序(集合具備比較性) 讓集合接收一個Comparator的實現類對象
到底使用那種集合
是否是鍵值對象形式:
是:Map
鍵是否需要排序:
是:TreeMap
否:HashMap
不知道,就使用HashMap。
否:Collection
元素是否唯一:
是:Set
元素是否需要排序:
是:TreeSet
否:HashSet
不知道,就使用HashSet
否:List
要安全嗎:
是:Vector(其實我們也不用它,后面我們講解了多線程以后,我在給你回顧用誰)
否:ArrayList或者LinkedList
增刪多:LinkedList
查詢多:ArrayList
不知道,就使用ArrayList
不知道,就使用ArrayList
-
集合的常見方法及遍歷方式
Collection: add() remove() contains() iterator() size() 遍歷: 增強for 迭代器 |--List get() 遍歷: 普通for |--Set Map: put() remove() containskey(),containsValue() keySet() get() value() entrySet() size() 遍歷: 根據鍵找值 根據鍵值對對象分別找鍵和值