Java 集合類可以用於存儲數量不等的多個對象,還可用於保存具有映射關係的關聯數組,而內存中對數據進行存儲和管理的“容器”有:數組,集合。
但數組有一定的弊端:
①數組的長度不可變
②數組存儲的數據類型比較單一
③數組的API較少,沒有插入,刪除等方法
④數組存儲元素是有序的,對於無序的無能爲力
而集合相對於數組的這些弊端做了優化:
①集合的長度可變
②集合可以存儲任意數據類型,因爲默認存儲的是Object類型
③ 集合中的API比較豐富,有增,刪,改,查,插,大小等操作
④集合底層存儲數據的結構較多(比如,數組,鏈表,二叉樹)
Collection集合與數組間的轉換
集合 –> 數組 : toArray()
數組 –> 集合 : Arrays.asList(T...t)
注意:
List:使用Collection集合存儲數據,要求數據所在的類滿足:必須重寫equals方法
Set:存儲元素所在類的要求:要求必須重寫hashCode和equals方法
TreeSet:自然排序的情況下該對象的類必須實現 Comparable 接口,且重寫compareTo()方法與equals()方法
說明:Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 實例,也不是 Vector 實例。 Arrays.asList(…) 返回值是一個固定長度的 List 集合
Java 集合可分爲 Collection 和 Map 兩種體系
Collection常用接口:
Set:元素無序、不可重複的集合
List:元素有序,可重複的集合
Map接口:具有映射關係“key-value對”的集合
|----Collection |----List |----ArrayList(主要實現類):底層是用數組實現的,線程不安全的,比Vector 效率高。增刪慢,查找快。 |----Vector:底層是用數組實現的,線程安全的,效率低 |----LinkedList:底層是用鏈表實現的,增刪快,查找慢 |----Set : 存儲的元素是無序的且不可重複的 |----HashSet(主要實現類):底層是創建了hashMap對象 |----LinkedHashSet:繼承了HashSet,底層實現原理和HashSet一樣。 但是LinkedHashSet可以按照元素添加的順序進行遍歷。因爲LinkedHashSet 底層維護了一對指針(鏈表)用來記錄元素添加的順序。 |----TreeSet:可以對對象中的屬性進行排序 |
Collection 接口是 List、Set 和 Queue 接口的父接口,該接口裏定義的方法既可用於操作 Set 集合,也可用於操作 List 和 Queue 集合。
注:JDK不提供此接口的任何直接實現,而是提供更具體的子接口(如:Set和List)實現。
在 Java5 之前,Java 集合會丟失容器中所有對象的數據類型,把所有對象都當成 Object 類型處理;從 JDK 5.0 增加了泛型以後,Java 集合可以記住容器中對象的數據類型
遍歷Collection的兩種方式: Iterator和foreach循環
增強for循環 :只能用於數組和集合
Iterator 接口: 用來遍歷集合中的元素
增強for循環:(foreach循環)
格式:
for(元素的類型 臨時變量 : 數組、集合的對象名){
}
Collection接口之List接口
List集合類中元素有序、且可重複,集合中的每個元素都有其對應的順序索引。
常用實現類主要區別:
|----ArrayList(主要實現類):底層是用數組實現的,線程不安全的,比Vector效率高。增刪慢 查找快。 |----Vector:底層是用數組實現的,線程安全的,效率低 |----LinkedList:底層是用鏈表實現的,增刪快,查找慢 |
①ArrayList底層是用數組存儲數據的,線程不安全的
②構造器
a)new ArrayList(); //默認創建一個長度爲10的數組
b)new ArrayList(int initialCapacity) //創建一個長度爲initalCapcity的數組
如何向ArrayList中添加數據?或ArrayList的底層實現?
創建一個ArrayList空參的對象,底層會創建一個長度爲10的數組。當我們向集合中放第11個元素的時候會進行擴容。擴容爲原來數組長度的1.5倍。再把原來數組中的內容copy到新的數組中。如果我們知道數組元素的個數建議使用new ArrayList(int initialCapacit)。
注意List的這兩個方法:
remove(int index)
remove(Object obj)
ArrayList al = new ArrayList();
al.add("aaa");
al.add("bbb");
al.add(1);
al.remove(1); //刪除當前集合對應的索引值上的元素。(bbb)
al.remove(new Integer(1)); //刪除當前集合中對應的元素(1)
System.out.println(al);
Collection接口之set接口
- Set接口是Collection的子接口,set接口沒有提供額外的方法
- Set 集合不允許包含相同的元素,如果試把兩個相同的元素加入同一個 Set 集合中,則添加操作失敗。
- Set 判斷兩個對象是否相同不是使用 == 運算符,而是根據 equals 方法
常用實現類
|----HashSet(主要實現類):底層是創建了hashMap對象 |----LinkedHashSet:繼承了HashSet,底層實現原理和HashSet一樣。 但是LinkedHashSet可以安照元素添加的順序進行遍歷。因爲LinkedHashSet 底層維護了一對指針(鏈表)用來記錄元素添加的順序。 |----TreeSet:可以對對象中的屬性進行排序 |
Set存儲的數據特點:無序的且不可重複的
無序的:指的不是隨機性,根據自定義類中的hashCode方法返回的值來決定在數組中存放的位置
不可重複的:指的是調用自定義類中的equals方法進行比較,如果返回的是true認爲兩個對象相同,反之則不相同。
如何向HashSet中添加數據?或HashSet的底層實現原理?
當我們向HashSet中存放數據a時,會先根據該對象中的hashCode方法返回的值決定存放在數組中的位置。如果存放的位置沒有其它元素那麼直接存放。如果存放的位置已經有了其它元素b時,會調用a的equals方法進行內容的比較。如果返回的是true那麼認爲兩個元素是相同的則不能再次存放。如果返回的是false那麼認爲兩個元素不同。以鏈表的形式進行存放。
注:
如果兩個元素的 equals() 方法返回 true,但它們的 hashCode() 返回值不相等,hashSet 將會把它們存儲在不同的位置,但依然可以添加成功。(可以是修改後的equals相等mx)
存儲元素所在類的要求:要求必須重寫hashCode和equals方法
Collection接口之set接口之TreeSetTreeSet 兩種排序方法:自然排序和定製排序。默認情況下,TreeSet 採用自然排序。
自然排序:
自然排序:TreeSet 會調用集合元素的 compareTo(Object obj) 方法來比較元素之間的大小關係,然後將集合元素按升序排列
如果試圖把一個對象添加到 TreeSet 時,則該對象的類必須實現 Comparable 接口。
實現 Comparable 的類必須實現 compareTo(Object obj) 方法,兩個對象即通過 compareTo(Object obj) 方法的返回值來比較大小。
因爲只有相同類的兩個實例纔會比較大小,所以向 TreeSet 中添加的應該是同一個類的對象
對於 TreeSet 集合而言,它判斷兩個對象是否相等的唯一標準是:兩個對象通過 compareTo(Object obj) 方法比較返回值
當需要把一個對象放入 TreeSet 中,重寫該對象對應的 equals() 方法時,應保證該方法與 compareTo(Object obj) 方法有一致的結果:如果兩個對象通過 equals() 方法比較返回 true,則通過 compareTo(Object obj) 方法比較應返回 0
定製排序:
TreeSet的自然排序是根據集合元素的大小,進行元素升序排列。如果需要定製排序,比如降序排列,可通過Comparator接口的幫助。需要重寫compare(T o1,T o2)方法。
利用int compare(T o1,T o2)方法,比較o1和o2的大小:如果方法返回正整數,則表示o1大於o2;如果返回0,表示相等;返回負整數,表示o1小於o2。
要實現定製排序,需要將實現Comparator接口的實例作爲形參傳遞給TreeSet的構造器。
此時,仍然只能向TreeSet中添加類型相同的對象。否則發生ClassCastException異常。
使用定製排序判斷兩個元素相等的標準是:通過Comparator比較兩個元素返回了0。
TreeSet可以對元素進行排序 要求:元素的類須必須一致
排序有兩種方式:自然排序 vs 定製排序
1自然排序
①實現Comparable接口
②重寫compareTo方法
③按照屬性進行排序
④添加元素
2 定製排序
①創建一個Comparator實現類的對象
②將Comparator對象傳入TreeSet的構造器中
③重寫compare方法
④按照屬性進行排序
⑤添加元素
自然排序的情況下該對象的類必須實現 Comparable 接口,且重寫compareTo()方法與equals()方法
Map接口
|----Map |----HashMap(主要實現類) : 底層是用數組來存放數據的(數組 + 鏈表),線程不安全的HashMap中可以存放null值 |----LinkedHashMap:繼承了HashMap底層實現和HashMap一樣。 LinkedHashMap可以安照添加元素的順序進行遍歷。因爲底層維護了一張鏈表用來記錄存放的元素的順序。 |----TreeMap:用來對Key中的元素進行排序。 |----Hashtable : 底層是用數組來存放數據的(數組 + 鏈表),線程安全的 Hashtable中不可以存放null值 |----Properties : 用來讀取配置文件中的內容。讀取的內容都是字符串。 key和value都是String類型 |
HashMap和Hashtable對比?
HashMap: 底層是用數組來存放數據的(數組 + 鏈表),線程不安全的HashMap中可以存放null值
Hashtable: 底層是用數組來存放數據的(數組 + 鏈表),線程安全的
Hashtable中不可以存放null值
HashMap的底層實現原理?
當我們向HashMap中存放一個元素(k1,v1),首先會根據k1的hashCode方法來決定在數組中存放的位置。如果當前位置沒有其它元素則直接存放。如果當前位置有其它元素(k2,v2),會調用k1的equals方法和k2進行對比。如果返回值是true則代表內容相同,那麼v1會覆蓋v2.如果返回的是false則以鏈表的形式進行存放。當鏈表的長度爲8時,鏈表將會改成紅黑樹進行存放。
Map之TreeMapTreeMap 的 Key 的排序:
自然排序:
TreeMap 的所有的 Key 必須實現 Comparable 接口,而且所有的 Key 應該是同一個類的對象,否則將會拋出 ClasssCastException
定製排序:
創建 TreeMap 時,傳入一個 Comparator 對象,該對象負責對 TreeMap 中的所有 key 進行排序。此時不需要 Map 的 Key 實現 Comparable 接口
結構說明:
①new HashMap() : 創建一個空參的構造器。那麼底層默認創建一個長度爲16加載因子爲0.75。當我們向集合中添加元素超過12時會進行擴容,擴容爲原來大小的2倍。
③HashSet的底層是:HashMap(將數據存放在Key中)
④LinkedHashSet的底層是:LinkedHashMap(將數據存放在Key中)
⑤TreeSet的底層是 : TreeMap(將數據存放在Key中)
Iterator迭代器接口
terator對象稱爲迭代器(設計模式的一種),主要用於遍歷 Collection 集合中的元素。
所有實現了Collection接口的集合類都有一個iterator()方法,用以返回一個實現了Iterator接口的對象。
Iterator 僅用於遍歷集合,Iterator 本身並不提供承裝對象的能力。如果需要創建 Iterator 對象,則必須有一個被迭代的集合。
常用方法:
hasNext() : 是否還有下一個元素
next(): ①指針下移 ②獲取元素
注:
Iterator常見的兩種錯誤:
Collection coll = new ArrayList();
coll.add("aaa");
coll.add(123); // 裝箱
coll.add(456);
//錯誤 方式一 :coll.iterator();因爲每次循環底層都創建了一個新的對象,如下圖
while(coll.iterator().hasNext()){
System.out.println(coll.iterator().next());
}
Iterator iterator = coll.iterator();
//錯誤方式二 : 因爲每next一次指針就會下移,一旦沒有元素就會報錯
while(iterator.next() != null){
System.out.println(iterator.next());
}
Collections工具類
注意Collection集合和Collections工具類的區別:
Collections是工具類:
Collections 是一個操作 Set、List 和 Map 等集合的工具類,Collections 中提供了一系列靜態的方法對集合元素進行排序、查詢和修改等操作,還提供了對集合對象設置不可變、對集合對象實現同步控制等方法
排序操作:(均爲static方法)
l reverse(List):反轉 List 中元素的順序
l shuffle(List):對 List 集合元素進行隨機排序
l sort(List):根據元素的自然順序對指定 List 集合元素按升序排序
l sort(List,Comparator):根據指定的 Comparator 產生的順序對 List 集合元素進行排序
l swap(List,int, int):將指定 list 集合中的 i 處元素和 j 處元素進行交換
查找、替換
l Object max(Collection):根據元素的自然順序,返回給定集合中的最大元素
l Object max(Collection,Comparator):根據 Comparator 指定的順序,返回給定集合中的最大元素
l Object min(Collection)
l Object min(Collection,Comparator)
l int frequency(Collection,Object):返回指定集合中指定元素的出現次數
l void copy(List dest,List src):將src中的內容複製到dest中
l boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替換 List 對象的所有舊值
注:
(
操作數組的工具類:Arrays
操作集合的工具類:Collections
)
再次總結底層實現:
List之 ArrayList的底層實現?
* 創建一個ArrayList空參的對象,底層會創建一個長度爲10的數組。當我們向集合中放第11個元素的時候會進行擴容。
* 擴容爲原來數組長度的1.5倍。再把原來數組中的內容copy到新的數組中。
* 如果我們知道數組元素的個數建議使用new ArrayList(int initialCapacit)。
Set之HashSet的底層實現原理?
* 當我們向HashSet中存放數據a時,會先根據該對象中的hashCode方法返回的值決定存放在數組中的位置。
* 如果存放的位置沒有其它元素那麼直接存放。如果存放的位置已經有了其它元素b時,會調用a的equals方法進行內容的比較。
* 如果返回的是true那麼認爲兩個元素是相同的則不能再次存放。如果返回的是false那麼認爲兩個元素不同。以鏈表的形式進行
* 存放。
Map之HashMap的底層實現原理?
當我們向HashMap中存放一個元素(k1,v1),首先會根據k1的hashCode方法來決定在數組中存放的位置。如果當前位置沒有其它元素則直接存放。如果當前位置有其它元素(k2,v2),會調用k1的equals方法和k2進行對比。如果返回值是true則代表內容相同,那麼v1會覆蓋v2.如果返回的是false則以鏈表的形式進行存放。當鏈表的長度爲8時,鏈表將會改成紅黑樹進行存放。