Collection集合框架html
在實際開發中,須要將使用的對象存儲於特定數據結構的容器中。而 JDK 提供了這樣的容器——集合框架,集合框架中包含了一系列不一樣數據結構(線性表、查找表)的實現類。
集合的引入:
數組的優點:是一種簡單的線性序列,能夠快速地訪問數組元素,效率高。若是從效率和類型檢查的角度講,數組是最好的。
數組的劣勢:不靈活。容量須要事先定義好,不能隨着需求的變化而擴容。
1)Collection 經常使用方法:
①int size():返回包含對象個數。 ②boolean isEmpty():返回是否爲空。
③boolean contains(Object o):判斷是否包含指定對象。
④void clear():清空集合。 ⑤boolean add(E e):向集合中添加對象。
⑥boolean remove(Object o):從集合中刪除對象。
⑦boolean addAll(Collection<? extends E > c):另外一個集合中的全部元素添加到集合
⑧boolean removeAll(Collection<?> c):刪除集合中與另一個集合中相同的原素
⑨Iterator<E> iterator():返回該集合的對應的迭代器
2)Collection 和 Collentions 的區別
Collection 是 java.util 下的接口,它是各類集合的父接口,繼承於它的接口主要有 Set和 List;
Collections 是個 java.util 下的類,是針對集合的幫助類,提供一系列靜態方法實現對各類集合的搜索、排序、線程安全化等操做。
一、List集合的實現類(ArrayList、LinkedList和Vector)
List 接口是 Collection 的子接口,用於定義線性表數據結構,元素可重複、有序的;能夠將 List 理解爲存放對象的數組,只不過元素個數能夠動態的增長或減小。
1)List 接口的兩個常見的實現類:ArrayList 和 LinkedList,分別用動態數組和鏈表的方式實現了 List 接口。List、ArrayList 和 LinkedList 均處於 java.util 包下。
2)能夠認爲 ArrayList 和 LinkedList 的方法在邏輯上徹底同樣,只是在性能上有必定的差異,ArrayList 更適合於隨機訪問,而 LinkedList 更適合於插入和刪除,在性能要求不是特別苛刻的情形下能夠忽略這個差異。
List接口經常使用的實現類有3個:ArrayList、LinkedList和Vector。java
ArrayList查詢效率高,增刪效率低,線程不安全。咱們通常使用它算法
1 package boom.collection; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Iterator; 6 import java.util.List; 7 import java.util.ListIterator; 8 9 /** 10 * 測試collection接口的方法 List接口 11 * 12 * @author Administrator 13 * 14 */ 15 public class ListTest { 16 17 public static void main(String[] args) { 18 //test01(); 19 //test02(); 20 test03(); 21 22 } 23 24 /** 25 * 集合帶索引順序的相關方法 26 */ 27 public static void test03() { 28 List<String> list = new ArrayList<>(); 29 30 // 添加元素 31 list.add("京東"); 32 list.add("阿里"); 33 list.add("騰訊"); 34 list.add("百度"); 35 System.out.println(list);// [京東, 阿里, 騰訊, 百度] 36 37 // 在指定索引位置插入新元素:index[0] 38 list.add(0, "網易"); 39 System.out.println(list);// [網易, 京東, 阿里, 騰訊, 百度] 40 41 // 移除指定位置的元素:index[3] 42 list.remove(3); 43 System.out.println(list);// [網易, 京東, 阿里, 百度] 44 45 // 指定位置更改元素:index[0] 46 list.set(0,"Google"); 47 System.out.println(list);// [Google, 京東, 阿里, 百度] 48 // 得到更改的元素 49 System.out.println(list.get(0));// Google 50 51 52 list.add("阿里"); 53 System.out.println(list);// [Google, 京東, 阿里, 百度, 阿里] 54 // 順序查找(角標0開始)指定的元素下標 55 System.out.println(list.indexOf("阿里"));// 2 56 // 從後往前找 57 System.out.println(list.lastIndexOf("阿里"));// 4 58 59 60 } 61 62 /** 63 * ArrayList_操做多個List_並集和交集及兩個list之間操做元素 64 */ 65 public static void test02() { 66 List<String> list01 = new ArrayList<String>(); 67 list01.add("AAA"); 68 list01.add("BBB"); 69 list01.add("CCC"); 70 71 List<String> list02 = new ArrayList<String>(); 72 list02.add("DDD"); 73 list02.add("CCC"); 74 list02.add("EEE"); 75 76 // 打印list01集合元素內容 77 System.out.println(list01); // [AAA, BBB, CCC] 78 79 // 把list02集合裏全部的元素都添加到list01集合裏:在末尾進行添加 80 list01.addAll(list02); 81 System.out.println(list01); // [AAA, BBB, CCC, DDD, CCC, EEE] 82 83 // 把list02集合裏的全部元素添加到01集合裏指定的位置,根據索引 84 list01.addAll(2, list02); 85 System.out.println(list01);// [AAA, BBB, DDD, CCC, EEE, CCC, DDD, CCC, EEE] 86 87 // 01集合裏是否包含02集合的全部元素 :true or false 88 System.out.println(list01.contains(list02)); // false 89 90 91 // 先進行打印,方便看效果 92 System.out.println("list01:"+list01); // list01:[AAA, BBB, DDD, CCC, EEE, CCC, DDD, CCC, EEE] 93 System.out.println("list02:"+list02); // list02:[DDD, CCC, EEE] 94 95 //移除集合01和集合02中都包含的元素,返回01集合 96 //list01.removeAll(list02); 97 //System.out.println(list01);// [AAA, BBB] 98 99 // 取本集合01和集合02中都包含的元素,移除非交集元素,返回01集合 100 list01.retainAll(list02); 101 System.out.println(list01); // [DDD, CCC, EEE, CCC, DDD, CCC, EEE] 102 103 } 104 105 /** 106 * List接口經常使用方法 107 */ 108 public static void test01() { 109 List<String> list = new ArrayList<String>(); 110 // 判斷集合是否爲空 111 System.out.println(list.isEmpty());// true 112 113 // 添加add,按下標順序添加 114 list.add("國產001"); 115 list.add("國產002"); 116 list.add("國產003"); 117 118 System.out.println(list.isEmpty());// false 119 120 // 打印 list自動調用toString方法 121 System.out.println(list.toString()); // [國產001, 國產002, 國產003] 122 System.out.println("集合的長度:" + list.size());// 集合的長度:3 123 124 // 指定位置索引添加元素 125 list.add(0, "new");// 在下標0的位置添加新元素 "new" 126 System.out.println(list); // [new, 國產001, 國產002, 國產003] 127 128 // 移除 129 list.remove(0);// 移除下標爲0的元素 130 System.out.println(list);// [國產001, 國產002, 國產003] 131 132 // 根據下標修改某個元素的值 133 // index[1]的位置更改成 "改" 134 list.set(1, "改"); 135 System.out.println(list);// [國產001, 改, 國產003] 136 137 // 測試集合是否包含指定的元素:true or false 138 System.out.println("是否包含指定元素:" + list.contains("國產"));// false 139 System.out.println("是否包含指定元素:" + list.contains("國產003"));// true 140 141 // 清空集合全部的元素 142 list.clear(); 143 System.out.println("清空全部元素:" + list); // 清空全部元素:[] 144 145 } 146 }
運行效果參照圖:
ArrayList_底層JDK源碼解讀數組
ArrayList:底層是用可變長度數組實現的存儲。
特色:查詢效率高,增刪效率低,線程不安全。
一、數組長度是有限的,而ArrayList是能夠存聽任意數量的對象,長度不受限制。
二、那麼它是怎麼實現的呢?
本質上就是經過定義新的更大的數組,將舊數組中的內容拷貝到新數組,來實現擴容。 ArrayList的Object數組初始化長度爲10,若是咱們存儲滿了這個數組,須要存儲第11個對象,就會定義新的長度更大的數組,並將原數組內容和新的元素一塊兒加入到新數組中。
LinkedList:底層用雙向鏈表實現的存儲。
特色:查詢效率低,增刪效率高,線程不安全。安全
Vector:Vector底層是用數組實現的List,相關的方法都加了同步檢查,所以「線程安全,效率低」
二、泛型
1)泛型是 JDK1.5 引入的新特性,泛型的本質是參數化類型。在類、接口、方法的定義過程當中,所操做的數據類型爲傳入的指定參數類型。全部的集合類型都帶有泛型參數,這樣在建立集合時能夠指定放入集合中的對象類型。同時,編譯器會以此類型進行檢查。
2)ArrayList 支持泛型,泛型尖括號裏的符號可隨便些,但一般大寫 E。
3)迭代器也支持泛型,可是迭代器使用的泛型應該和它所迭代的集合的泛型類型一致!
4)泛型只支持引用類型,不支持基本類型,但可使用對應的包裝類
5)若是泛型不指定類型的話,默認爲 Object 類型。
三、List 高級-數據結構:Queue 隊列
隊列(Queue)是經常使用的數據結構,能夠將隊列當作特殊的線性表,隊列限制了對線性表的訪問方式:只能從線性表的一端添加(offer)元素,從另外一端取出(poll)元素。Queue接口:在包 java.util.Queue。
1)隊列遵循先進先出原則:FIFO(First Input First Output)隊列不支持插隊,插隊是不道德的。
2)JDK 中提供了 Queue 接口,同時使得 LinkedList 實現了該接口(選擇 LinkedList 實現Queue 的緣由在於 Queue常常要進行插入和刪除的操做,而 LinkedList 在這方面效率較高)。
四、List 高級-數據結構:Deque 棧
棧(Deque)是經常使用的數據結構,是 Queue 隊列的子接口,所以 LinkedList 也實現了 Deque接口。棧將雙端隊列限制爲只能從一端入隊和出隊,對棧而言便是入棧和出棧。例如:子彈夾就是一種棧結構。在包 java.util.Deque 下。
1)棧遵循先進後出的原則:FILO(First Input Last Output)。
2)經常使用方法:
①push:壓入,向棧中存入數據。
②pop:彈出,從棧中取出數據。
③peek:獲取棧頂位置的元素,但不取出
五、Set集合的實現類(HashSet 和 TreeSet )
Set容器特色:無序、不可重複。無序指Set中的元素沒有索引,咱們只能遍歷查找;不可重複指不容許加入重複的元素。更確切地講,新元素若是和Set中某個元素經過equals()方法對比爲true,則不能加入;甚至,Set中也只能放入一個null元素,不能多個。
1)HashSet 和 TreeSet 是 Set 集合的兩個常見的實現類,分別用 hash 表和排序二叉樹的方式實現了 Set 集合。HashSet 是使用散列算法實現 Set 的。
2)Set 集合沒有 get(int index)方法,咱們不能像使用 List 那樣,根據下標獲取元素。想獲取元素須要使用 Iterator。
3)向集合添加元素也使用 add 方法,可是 add 方法不是向集合末尾追加元素,由於無序。
HashSet:採用哈希算法實現,底層實際是用HashMap實現的(HashSet本質就是一個簡化版的HashMap),所以,查詢效率和增刪效率都比較高。
TreeSet:底層實際是用TreeMap實現的,內部維持了一個簡化版的TreeMap,經過key來存儲Set的元素。
(1) 因爲是二叉樹,須要對元素作內部排序。 若是要放入TreeSet中的類沒有實現Comparable接口,則會拋出異常:java.lang.ClassCastException。
(2) TreeSet中不能放入null元素。
六、Map集合的實現類(HashMap、TreeMap、HashTable、Properties等)
Map就是用來存儲「鍵(key)-值(value) 對」的。 Map類中存儲的「鍵值對」經過鍵來標識,因此Key 不能重複,但所保存的 Value 能夠重複。
HashMap和HashTable
HashMap採用哈希算法實現,是Map接口最經常使用的實現類。 因爲底層採用了哈希表存儲數據,鍵不能重複,若是發生重複(是否重複經過equals方法),新的鍵值對會替換舊的鍵值對。
特色:HashMap在查找、刪除、修改方面都有很是高的效率。
HashTable類和HashMap用法幾乎同樣,底層實現幾乎同樣,只不過HashTable的方法添加了synchronized關鍵字確保線程同步檢查,效率較低。
HashMap與HashTable的區別
1. HashMap:線程不安全,效率高。容許key或value爲null。
2. HashTable:線程安全,效率低。不容許key或value爲null。
TreeMap使用和底層原理_Comparable接口_HashTable特色(HashTable: 線程安全,效率低。不容許key或value爲null。)
TreeMap是紅黑二叉樹的典型實現。咱們打開TreeMap的源碼,發現裏面有一行核心代碼:private
transient
Entry<K,V> root =
null
;
TreeMap和HashMap實現了一樣的接口Map,用法對於調用者來講沒有區別。HashMap效率高於TreeMap;在須要排序(comparable)的Map時才選用TreeMap。
數據結構
Collection集合框架的總結:
1. Collection 表示一組對象,它是集中、收集的意思,就是把一些數據收集起來。
2. Collection接口的兩個子接口:
1) List中的元素有順序,可重複。經常使用的實現類有ArrayList、LinkedList和 vector。
Ø ArrayList特色:查詢效率高,增刪效率低,線程不安全。
Ø LinkedList特色:查詢效率低,增刪效率高,線程不安全。
Ø vector特色:線程安全,效率低,其它特徵相似於ArrayList。
2) Set中的元素沒有順序,不可重複。經常使用的實現類有HashSet和TreeSet。
Ø HashSet特色:採用哈希算法實現,查詢效率和增刪效率都比較高。
Ø TreeSet特色:內部須要對存儲的元素進行排序。所以,咱們對應的類須要實現Comparable接口。才能根據compareTo()方法比較對象之間的大小,才能進行內部排序。
3. 實現Map接口的類用來存儲鍵(key)-值(value) 對。Map 接口的實現類有HashMap和TreeMap等。Map類中存儲的鍵-值對經過鍵來標識,因此鍵值不能重複。
4. Iterator對象稱做迭代器,用以方便的實現對容器內元素的遍歷操做。
5. 類 java.util.Collections 提供了對Set、List、Map操做的工具方法。
6. 以下狀況,可能須要咱們重寫equals/hashCode方法:
1) 要將咱們自定義的對象放入HashSet中處理。
2) 要將咱們自定義的對象做爲HashMap的key處理。
3) 放入Collection容器中的自定義對象後,可能會調用remove、contains等方法時。
7. JDK1.5之後增長了泛型。泛型的好處:
1) 向集合添加數據時保證數據安全。
2) 遍歷集合元素時不須要強制轉換。框架