JAVA 集合類(Collection)、List、Set、Map、Collections與Arrays、泛型
1. 集合
堆疊、佇列資料結構的特點
1.1. 什麼是集合
儲存物件的容器,面嚮物件語言對事物的體現都是以物件的形式,所以為了方便對多個物件的操作,儲存物件,集合是儲存物件最常用的一種方式。
集合的出現就是為了持有物件。集合中可以儲存任意型別的物件, 而且長度可變。在程式中有可能無法預先知道需要多少個物件, 那麼用陣列來裝物件的話, 長度不好定義, 而集合解決了這樣的問題。
1.2. 集合和陣列的區別
陣列和集合類都是容器
陣列長度是固定的,集合長度是可變的。陣列中可以儲存基本資料型別,集合只能儲存物件陣列中儲存資料型別是單一的,集合中可以儲存任意型別的物件。
集合類的特點
用於儲存物件,長度是可變的,可以儲存不同型別的物件。
1.2.1. 陣列的缺點
儲存型別單一的資料容器,操作複雜(陣列一旦宣告好不可變)CRUD
1.3. 集合的分類
集合做什麼
1:將物件新增到集合
2:從集合中刪除物件
3: 從集合中查詢一個物件
4:從集合中修改一個物件就是增刪改查
注意:集合和陣列中存放的都是物件的引用而非物件本身
Java工程師對不同的容器進行了定義,雖然容器不同,但是還是有一些共性可以抽取最後抽取了一個頂層介面,那麼就形成了一個集合框架。如何學習呢?當然是從頂層學起,頂層裡邊具有最共性,最基本的行為。具體的使用,就要選擇具體的容器了。為什麼? 因為不斷向上抽取的東西有可能是不能建立物件的.抽象的可能性很大,並且子類物件的方法更多一些.
集合框架體系
---|Collection: 單列集合 ---|List: 有儲存順序, 可重複 ---|ArrayList: 陣列實現, 查詢快, 增刪慢 由於是陣列實現, 在增和刪的時候會牽扯到陣列 增容, 以及拷貝元素. 所以慢。陣列是可以直接 按索引查詢, 所以查詢時較快 ---|LinkedList: 連結串列實現, 增刪快, 查詢慢 由於連結串列實現, 增加時只要讓前一個元素記住自 己就可以, 刪除時讓前一個元素記住後一個元 素, 後一個元素記住前一個元素. 這樣的增刪效 率較高但查詢時需要一個一個的遍歷, 所以效率 較低 ---|Vector: 和ArrayList原理相同, 但執行緒安全, 效率略低 和ArrayList實現方式相同, 但考慮了執行緒安全問 題, 所以效率略低 ---|Set: 無儲存順序, 不可重複 ---|HashSet ---|TreeSet ---|LinkedHashSet ---| Map: 鍵值對 ---|HashMap ---|TreeMap ---|HashTable ---|LinkedHashMap |
為什麼出現這麼多集合容器,因為每一個容器對資料的儲存方式不同,這種儲存方式稱之為資料結構(data structure)
注意 集合和陣列中存放的都是物件的引用。
1.4. 什麼時候該使用什麼樣的集合
Collection | 我們需要儲存若干個物件的時候使用集合。 |
List | 如果我們需要保留儲存順序, 並且保留重複元素, 使用List. 如果查詢較多, 那麼使用ArrayList 如果存取較多, 那麼使用LinkedList 如果需要執行緒安全, 那麼使用Vector |
Set | 如果我們不需要保留儲存順序, 並且需要去掉重複元素, 使用Set. 如果我們需要將元素排序, 那麼使用TreeSet 如果我們不需要排序, 使用HashSet, HashSet比 TreeSet效率高. 如果我們需要保留儲存順序, 又要過濾重複元素, 那麼使用LinkedHashSet |
2. 集合類(Collection)
Collection介面有兩個子介面:
List(連結串列|線性表)
Set(集)
特點:
Collection中描述的是集合共有的功能(CRUD)
List可存放重複元素,元素存取是有序的
Set不可以存放重複元素,元素存取是無序的
java.util.Collection ---| Collection 描述所有介面的共性 ----| List介面 可以有重複元素的集合 ----| Set 介面 不可以有重複元素的集合 |
2:學習集合物件
學習Collection中的共性方法,多個容器在不斷向上抽取就出現了該體系。發現Collection介面中具有所有容器都具備的共性方法。查閱API時,就可以直接看該介面中的方法。並建立其子類物件對集合進行基本應用。當要使用集合物件中特有的方法,在檢視子類具體內容。
檢視api 文件Collection在在java.util 中(注意是大寫Collection)
注意在現階段遇到的 E T 之類的型別,需要暫時理解為object 因為涉及到了泛型.
3:建立集合物件,使用Collection中的List的具體實現類ArrayList
1:Collection coll=new Arraylist();
2.1. Collection介面的共性方法
增加: 1:add() 將指定物件儲存到容器中 add 方法的引數型別是Object 便於接收任意物件 2:addAll() 將指定集合中的元素新增到呼叫該方法和集合中 刪除: 3:remove() 將指定的物件從集合中刪除 4:removeAll() 將指定集合中的元素刪除 修改 5:clear() 清空集合中的所有元素 判斷 6:isEmpty() 判斷集合是否為空 7:contains() 判斷集合何中是否包含指定物件 8:containsAll() 判斷集合中是否包含指定集合 使用equals()判斷兩個物件是否相等 獲取: 9:int size() 返回集合容器的大小 轉成陣列10: toArray() 集合轉換陣列 |
2.1.1. 增加:
publicstaticvoid main(String[] args) { Collection list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); System.out.println(list); // [計算機網路, 現代作業系統, java程式設計思想] // 增加2 將list容器元素新增到list2容器中 Collection list2 = new ArrayList(); list2.add("java核心技術"); list2.addAll(list); list2.add("java語言程式設計"); System.out.println(list2); // [java核心技術, 計算機網路, 現代作業系統, java程式設計思想, java語言程式設計] } |
2.1.2. 刪除:
// 刪除1 remove boolean remove = list2.remove("java核心技術"); System.out.println(remove); // true System.out.println(list2); // //刪除2 removeAll() 將list中的元素刪除 boolean removeAll = list2.removeAll(list); System.out.println(removeAll);//true System.out.println(list2);//[java語言程式設計] |
2.1.3. 修改:
publicstaticvoid main(String[] args) { Collection list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); System.out.println(list); // 修改 clear() 清空集合中的所有元素 list.clear(); System.out.println(list); //[] } |
2.1.4. 判斷:
publicstaticvoid main(String[] args) { Collection list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); System.out.println(list); boolean empty = list.isEmpty(); System.out.println(empty);// false boolean contains = list.contains("java程式設計思想"); System.out.println(contains);// true Collection list2 = new ArrayList(); list2.add("水許傳"); boolean containsAll = list.containsAll(list2); System.out.println(containsAll);// false } |
2.1.5. 獲取:
publicstaticvoid main(String[] args) { Collection list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); System.out.println(list); // 獲取 集合容器的大小 int size = list.size(); System.out.println(size); } |
2.1.6. 練習:集合中新增自定義物件
該案例要求完成使用集合:
publicstaticvoid main(String[] args) { // 建立集合物件 Collection coll = new ArrayList(); // 建立Person物件 Person p1 = new Person("jack", 25); Person p2 = new Person("rose", 22); Person p3 = new Person("lucy", 20); Person p4 = new Person("jack", 25); // 集合中新增一些Perosn // 刪除指定Person // 刪除所有Person // 判斷容器中是否還有Person // 判斷容器中是否包含指定Person // 獲取容器中Person的個數 // 將容器變為陣列,遍歷除所有Person } |
分析:
1:Person類
1:姓名和年齡
2:重寫hashCode和equals方法
1:如果不重寫,呼叫Object類的equals方法,判斷記憶體地址,為false
1:如果是Person類物件,並且姓名和年齡相同就返回true
2:如果不重寫,呼叫父類hashCode方法
1:如果equals方法相同,那麼hashCode也要相同,需要重寫hashCode方法
3:重寫toString方法
1:不重寫,直接呼叫Object類的toString方法,列印該物件的記憶體地址
Person類
class Person { private String name; privateintage; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } @Override publicint hashCode() { returnthis.name.hashCode() + age; } @Override publicboolean equals(Object obj) { if (!(obj instanceof Person)) { returnfalse; } Person p = (Person) obj; returnthis.name.equals(p.name) && this.age == p.age; } @Override public String toString() { return"Person :name=" + name + ", age=" + age; } } |
publicstaticvoid main(String[] args) { Person p1 = new Person("張三", 19); Person p2 = new Person("李四", 20); Person p3 = new Person("王五", 18); Collection list = new ArrayList(); list.add(p1); list.add(p2); list.add(p3); // isEmpty() 判斷集合是否為空 boolean empty = list.isEmpty(); System.out.println(empty); // 返回集合容器的大小 int size = list.size(); System.out.println(size); // contains()判斷集合何中是否包含指定物件 boolean contains = list.contains(p1); System.out.println(contains); // remove(); 將指定的物件從集合中刪除 list.remove(p1); // clear() 清空集合中的所有元素 list.clear(); System.out.println(list); } |
//使用集合儲存自定義物件2 class Book { private String name; privatedoubleprice; public Book() { } public Book(String name, double price) { this.name = name; this.price = price; } public String getName() { returnname; } publicvoid setName(String name) { this.name = name; } publicdouble getPrice() { returnprice; } publicvoid setPrice(double price) { this.price = price; } @Override publicint hashCode() { return (int) (this.name.hashCode() + price); } @Override publicboolean equals(Object obj) { if (!(obj instanceof Book)) { returnfalse; } Book book = (Book) obj; returnthis.name.equals(book.name) && this.price == book.price; } @Override public String toString() { return"book:@ name:" + this.name + ", price:" + this.price; } } publicclass Demo1 { publicstaticvoid main(String[] args) { Collection col = new ArrayList(); col.add(new Book("think in java", 100)); col.add(new Book("core java", 200));System.out.println(col); } } |
2.2. List
---| Iterable 介面 Iterator iterator() ----| Collection 介面 ------| List 介面 元素可以重複,允許在指定位置插入元素,並通過索 引來訪問元素 |
2.2.1. List集合特有方法
1:增加 void add(int index, E element) 指定位置新增元素 boolean addAll(int index, Collection c) 指定位置新增集合 2:刪除 E remove(int index) 刪除指定位置元素 3:修改 E set(int index, E element) 返回的是需要替換的集合中的元素 4:查詢: E get(int index) 注意: IndexOutOfBoundsException int indexOf(Object o) // 找不到返回-1 lastIndexOf(Object o) 5:求子集合 List<E> subList(int fromIndex, int toIndex) // 不包含toIndex |
2.2.1.1. 增加
publicstaticvoidmain(String[] args) { List list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); System.out.println(list); // add,在0角標位置新增一本書 list.add(0, "舒克和貝塔"); System.out.println(list); // 在list2集合的1角標位置新增list集合元素 List list2 = new ArrayList(); list2.add("史記"); list2.add("資治通鑑"); list2.add("全球通史"); boolean addAll = list2.addAll(1, list); System.out.println(addAll); //trueSystem.out.println(list2); } |
2.2.1.2. 刪除
publicstaticvoid main(String[] args) { List list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); System.out.println(list); // 刪除0角標元素 Object remove = list.remove(0); System.out.println(remove); } |
2.2.1.3. 修改:
publicstaticvoid main(String[] args) { List list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); System.out.println(list); // 修改2角標位置的書,返回的原來2角標位置的書 Object set = list.set(2, "邊城"); System.out.println(set); //java程式設計思想 System.out.println(list); } |
查詢
List list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); System.out.println(list); // 查詢: E get(int index)注意角標越界 Object set = list.get(list.size() - 1); System.out.println(set); // java語言程式設計 System.out.println(list); list.get(list.size()); //IndexOutOfBoundsException } |
2.2.1.4. 查詢
publicstaticvoid main(String[] args) { List list = new ArrayList(); // 增加:add() 將指定物件儲存到容器中 list.add("計算機網路"); list.add("現代作業系統"); list.add("java程式設計思想"); list.add("java核心技術"); list.add("java語言程式設計"); list.add("java程式設計思想"); System.out.println(list); // 查詢: E get(int index) 注意角標越界 Object set = list.get(list.size() - 1); System.out.println(set); // java語言程式設計 System.out.println(list); // list.get(list.size()); //IndexOutOfBoundsException // indexOf(Object o) 返回第一次出現的指定元素的角標 int indexOf = list.indexOf("java程式設計思想"); System.out.println(indexOf); // 2 // 沒有找到,返回-1 int indexOf2 = list.indexOf("三國志"); System.out.println(indexOf2); // -1 // lastIndexOf 返回最後出現的指定元素的角標 int lastIndexOf = list.lastIndexOf("java程式設計思想"); System.out.println(lastIndexOf); // 5 } |
2.2.2. ArrayList
--| Iterable ----| Collection ------| List ---------| ArrayList 底層採用陣列實現,預設10。每次增長 60%,((oldCapacity * 3)/2 + 1) 查詢快,增刪慢。 ---------| LinkedList |
ArrayList: