Java知識梳理 | 詳析三大集合類(附實用例程 + 實踐練習題)
1. 集合類概述
1.1. java.util包中提供了一些集合類,這些集合類又被稱為容器。
1.2. 關於容器,集合類與陣列的不同之處:
- 陣列的長度是
固定
的,集合的長度是可變
的; - 陣列用來存放
基本型別的資料
,集合用來存放物件的引用
。
1.3. 常用的集合有List集合、Set集合和Map集合;
List與Set繼承了 Collection介面
, 各介面
還提供了 不同的實現類
。
常用集合類的繼承關係如下:

2. Collection介面
- Collection介面是層次結構中的根介面;
- 構成Collection的單位稱為
元素
; - Collection介面通常不能直接使用,但該介面提供了
新增元素、刪除元素、管理資料
的方法。 -
由於List介面與Set介面都繼承了Collection介面,因此這些方法對List集合與Set集合是通用的。
常用方法如下表:
下面是一個綜合例項,把表中的方法都用一遍:
(Ps:
- iterator迭代器有點兒像一個指標一樣的東西,指向list物件中的某一個元素;
- it.hasNext()中迭代器的hasNext()第一次用的時候,指向第一個元素,next()同理)
package com.lzw; import java.util.*; public class Muster { // 建立類Muster public static void main(String args[]) { Collection<String> list = new ArrayList<>(); // 例項化集合類物件 list.add("a"); // 向集合新增資料 list.add("b"); list.add("c"); list.add("d"); list.add("e"); System.out.println("Now add a&b&c&d&e to the list , its size is:"+list.size()); System.out.println("Print out all element of the list:"); Iterator<String> it = list.iterator(); // 建立迭代器 while (it.hasNext()) { // 判斷是否有下一個元素 String str = (String) it.next(); // 獲取集合中元素 System.out.println(str); } System.out.println("------------------------------------------------"); list.remove("a"); list.remove("b"); list.remove("c"); System.out.println("Now remove a&b&c of the list , its size is:"+list.size()); System.out.println("Print out all element of the list:"); Iterator<String> it1 = list.iterator(); while(it1.hasNext()){ String str = (String)it1.next(); System.out.println(str); } System.out.println("Now is the list Empty?"+list.isEmpty()); System.out.println("------------------------------------------------"); list.remove("d"); list.remove("e"); System.out.println("Now remove d&e of the list , its size is:"+list.size()); System.out.println("Now is the list Empty?"+list.isEmpty()); } }
輸出結果:
Now add a&b&c&d&e to the list , its size is:5 Print out all element of the list: a b c d e ------------------------------------------------ Now remove a&b&c of the list , its size is:2 Print out all element of the list: d e Now is the list Empty?false ------------------------------------------------ Now remove d&e of the list , its size is:0 Now is the list Empty?true
3. List集合
- List集合包括List介面以及
介面
的所有實現類
。 - List集合中的元素
允許重複
,各元素的順序
就是物件插入的順序
。 - 類似Java陣列,使用者可通過使用
索引(元素在集合中的位置)
來訪問集合中的元素。
3.1 List介面
List介面繼承了 Collection介面
,因此包含Collection中的所有方法。
此外,List介面還定義了以下兩個非常重要的方法:
get(int index)
:獲得指定索引位置的元素;
set(int index,Object obj)
:將集合中指定索引位置的物件修改為指定的物件。
3.2 List介面的實現類
List介面的常用實現類有 ArrayList
與 LinkedList
.
ArrayList
類
a. 實現了 可變的陣列
,允許 儲存所有元素
,包括 null
,並可以根據索引位置對集合進行快速的隨機訪問;
b. 缺點是向指定的索引位置插入物件或刪除物件的速度較慢。
LinkedList
類
a.採用 連結串列結構
儲存物件。
b.優點是便於向集合中插入和刪除物件,需要向集合中 插入、刪除物件
時,使用LinkedList類實現的List集合的效率較高:
c. 但對於 隨機訪問集合中的物件
,使用LinkedList類實現List集合的效率較低。
使用List集合時通常 宣告
為List型別,可通過 不同的實現類
來 例項化
集合。
分別通過 ArrayList
、 LinkedList
類例項化 List集合
,程式碼如下:
List<E> list = new ArrayList<>(); List<E> list2 = new LinkedList<>();
在上面的程式碼中, E
可以是合法的 Java資料型別
。
例如,如果集合中的元素為 字串型別
,那麼 E
可以修改為 String
。
下面是一個綜合例項:
import java.util.*; public class Gather { // 建立類Gather public static void main(String[] args) { // 主方法 List<String> list = new ArrayList<>(); // 建立集合物件 list.add("a"); // 向集合新增元素 list.add("b"); list.add("c"); list.add("d"); list.add("e"); int i = (int) (Math.random() * (list.size())); // 獲得0~4之間的隨機數 System.out.println("隨機獲取陣列中的元素:" + list.get(i)); list.remove(2); // 將指定索引位置的元素從集合中移除 System.out.println("將索引是'2'的元素從陣列移除後,陣列中的元素是:"); for (int j = 0; j < list.size(); j++) { // 迴圈遍歷集合 System.out.println(list.get(j)); } } }
輸出結果:
隨機獲取陣列中的元素:c 將索引是'2'的元素從陣列移除後,陣列中的元素是: a b d e
4. Set集合
- Set集合中的物件
不按特定的方式排序
,只是簡單地把物件加入集合中
; - Set集合中
不能包含重複物件
; - Set集合由
Set介面
和Set介面的實現類
組成。 - Set介面繼承了
Collection介面
,因此包含Collection介面的所有方法
。
Set介面常用的實現類有 HashSet類
與 TreeSet類
。
HashSet
類
a. 實現 Set介面
,由 雜湊表(實際上是一個HashMap例項)
支援。
b. 它 不保證Set的迭代順序
,特別是它不 保證該順序恆久不變
。
c .此類 允許使用null元素
。
TreeSet
類
a. 不僅實現了 Set介面
,還實現了 java.util.SortedSet介面
,
遍歷集合時
按照
自然順序遞增排序
;
*********%%%%%%%%%%***********
c. 也可以按照指定 比較器
遞增排序;
d. 即可以通過比較器對用TreeSet類實現的Set集合中的物件進行排序。
TreeSet類新增的方法如下表:



幾個需要注意的地方:
-
compareTo()
方法中書寫的內容正是TreeSet類實現的Set集合在遍歷集合時
那自然順序遞增排序
的依據; - 使用
compareTo()
方法的前提是要讓使用的類實現Comparable介面
; - Set順序遍歷時,依據
compareTo()
方法中書寫的規則進行自然順序遞增排序
,而非add()
的順序; - headSet()/subSet()/tailSet()三個方法再擷取時,所謂的“之前、之後、之間”也是相對於
自然順序遞增排序
之的Set結合,而非add()
的順序; - 注意上表中
包含
和不包含
的運用;
(可參考下面例項加深瞭解)
下面是一個綜合例項:
import java.util.*; public class UpdateStu implements Comparable<Object> { String name; long id; //構造方法 public UpdateStu(String name, long id) { this.id = id; this.name = name; } //定義排序規則 public int compareTo(Object o) { UpdateStu upstu = (UpdateStu) o; int result = id > upstu.id ? 1 : (id == upstu.id ? 0 : -1); return result; } //getter & setter public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) { UpdateStu stu1 = new UpdateStu("李同學", 01011);//吶!01011是八進位制!!!!!!!!!!!!!!!!! UpdateStu stu2 = new UpdateStu("陳同學", 01021); UpdateStu stu3 = new UpdateStu("王同學", 01051); UpdateStu stu4 = new UpdateStu("馬同學", 01012); TreeSet<UpdateStu> tree = new TreeSet<>(); tree.add(stu1); tree.add(stu2); tree.add(stu3); tree.add(stu4); Iterator<UpdateStu> it = tree.iterator(); System.out.println("Set集合中的所有元素:"); while (it.hasNext()) { UpdateStu stu = (UpdateStu) it.next(); System.out.println(stu.getId() + " " + stu.getName()); } System.out.println("李馬陳王是自然排序,其對應的物件名順序是:"); System.out.println("stu1"); System.out.println("stu4"); System.out.println("stu2"); System.out.println("stu3"); System.out.println(" "); System.out.println("tree.first().getName():" + tree.first().getName()); System.out.println("tree.last().getName():" + tree.last().getName()); System.out.println("------------------------------------------------"); it = tree.headSet(stu3).iterator(); System.out.println("擷取stu3前面部分的集合:"); while (it.hasNext()) { UpdateStu stu = (UpdateStu) it.next(); System.out.println(stu.getId() + " " + stu.getName()); } System.out.println("------------------------------------------------"); it = tree.subSet(stu2, stu3).iterator(); System.out.println("擷取stu2&stu3中間部分的集合"); while (it.hasNext()) { UpdateStu stu = (UpdateStu) it.next(); System.out.println(stu.getId() + " " + stu.getName()); } System.out.println("------------------------------------------------"); it = tree.tailSet(stu1).iterator(); System.out.println("擷取stu1後面部分的集合"); while (it.hasNext()) { UpdateStu stu = (UpdateStu) it.next(); System.out.println(stu.getId() + " " + stu.getName()); } } }
輸出結果:
Set集合中的所有元素: 521 李同學 522 馬同學 529 陳同學 553 王同學 李馬陳王是自然排序,其對應的物件名順序是: stu1 stu4 stu2 stu3 tree.first().getName():李同學 tree.last().getName():王同學 ------------------------------------------------ 擷取stu3前面部分的集合: 521 李同學 522 馬同學 529 陳同學 ------------------------------------------------ 擷取stu2&stu3中間部分的集合 529 陳同學 ------------------------------------------------ 擷取stu1後面部分的集合 521 李同學 522 馬同學 529 陳同學 553 王同學
最後強調:
- 存入
TreeSet類
實現的set集合
必須實現Comparable介面
,該介面中的compareTo(Object o)
方法
比較此物件(this/實現本介面的類的例項化物件)
與指定物件(傳進來的作為引數的物件)
的順序; - 如果該物件小於、等於或大於指定物件,則分別返回負整數、0或正整數。
5. Map集合
- Map集合沒有繼承
Collection
介面,其提供的是key到value的對映
; - Map中不能包含相同的
key
,每個key
只能對映一個value
; - key還決定了
儲存物件在對映中的儲存位置
,但不是由key物件本身
決定的,而是通過一種“雜湊技術”
進行處理,產生一個雜湊碼的整數值
; -
雜湊碼
通常用作一個偏移量
,該偏移量對應分配給對映的記憶體區域的起始位置
,從而確定儲存物件在對映中的儲存位置
; - Map集合包括Map介面以及Map介面的所有實現類。
5.1 Map介面
- Map介面提供了將key對映到值的物件。
- 一個對映不能包含重複的key,每個key最多隻能對映到一個值。
-
Map介面中同樣提供了集合的常用方法,除此之外還包括如下表所示的常用方法:
下面是一個綜合例項:
import java.util.*; public class UpdateStu { public static void main(String[] args) { Map<String,String> map = new HashMap<>(); // 建立Map例項 map.put("01", "李同學"); // 向集合中新增物件 map.put("02", "魏同學"); map.put("03", "王同學"); map.put("04", "陳同學"); map.put("05", "張同學"); map.put("06", "趙同學"); Set<String> set = map.keySet(); // 構建Map集合中所有key物件的集合 Iterator<String> it = set.iterator(); // 建立集合迭代器 System.out.println("key集合中的元素(map.keySet() + iterator()):"); while (it.hasNext()) { // 遍歷集合 System.out.println(it.next()); } System.out.println("------------------------------------------------"); Collection<String> coll = map.values(); // 構建Map集合中所有values值集合 it = coll.iterator(); System.out.println("values集合中的元素(map.values() + iterator()):"); while (it.hasNext()) { // 遍歷集合 System.out.println(it.next()); } System.out.println("------------------------------------------------"); System.out.println("map.get(\"01\")" + map.get("01")); System.out.println("map.get(\"02\")" + map.get("02")); System.out.println("map.get(\"03\")" + map.get("03")); System.out.println("------------------------------------------------"); System.out.println("map.containsKey(\"01\")" + map.containsKey("01")); System.out.println("map.containsKey(\"10\")" + map.containsKey("10")); System.out.println("map.containsValue(\"李同學\")" + map.containsValue("李同學")); System.out.println("map.containsValue(\"許同學\")" + map.containsValue("許同學")); } }
輸出結果:
key集合中的元素(map.keySet() + iterator()): 01 02 03 04 05 06 ------------------------------------------------ values集合中的元素(map.values() + iterator()): 李同學 魏同學 王同學 陳同學 張同學 趙同學 ------------------------------------------------ map.get("01")李同學 map.get("02")魏同學 map.get("03")王同學 ------------------------------------------------ map.containsKey("01")true map.containsKey("10")false map.containsValue("李同學")true map.containsValue("許同學")false
注意:Map集合中允許值物件是null,而且沒有個數限制,例如,可通過“map.put("05",null)”語句向集合中新增物件。
5.2 Map介面的實現類
- Map介面常用的實現類有
HashMap
和TreeMap
; - 建議使用
HashMap類
實現Map集合; - 由
HashMap類
實現的Map集合新增和刪除對映關係效率更高
; - HashMap是基於
雜湊表
的Map介面
的實現; - HashMap通過
雜湊碼
對其內部的對映關係進行快速查詢
; -
TreeMap
中的對映關係存在一定的順序
; - 如果希望Map集合中的物件也存在一定的順序,應該使用TreeMap類實現Map集合。
HashMap
類
a .是基於雜湊表的Map介面的實現;
b. 此實現 提供所有可選的對映操作
, 並允許使用null值和null鍵
,但必須保證 鍵的唯一性
。
c .HashMap通過雜湊表對其內部的對映關係進行 快速查詢
。
d. 此類 不保證
對映的順序,特別是它不保證該順序恆久不變。
TreeMap
類
a. 不僅實現了Map介面,還實現了java.util.SortedMap接囗,因此,集合中的對映關係具有一定的順序。
b. 但在 新增、刪除和定位對映關係
時,TreeMap類比HashMap類 效能稍差
。
c. 由於TreeMap類實現的Map集合中的對映關係是根據鍵物件 按照一定的順序排列
的,因此 不允許鍵物件是null
。
可以通過HashMap類建立Map集合,
當需要順序輸出時,再建立一個完成相同對映關係的TreeMap類例項。如下的綜合例項:
首先是一個Emp類檔案:
public class Emp { private String e_id; private String e_name; public Emp( String e_id,String e_name) { this.e_id = e_id; this.e_name = e_name; } public String getE_id() { return e_id; } public void setE_id(String e_id) { this.e_id = e_id; } public String getE_name() { return e_name; } public void setE_name(String e_name) { this.e_name = e_name; } }
測試用主類:
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class MapText { // 建立類MapText public static void main(String[] args) { // 主方法 Map<String, String> map = new HashMap<>(); // 由HashMap實現的Map物件 Emp emp = new Emp("351", "張三"); // 建立Emp物件 Emp emp2 = new Emp("512", "李四"); Emp emp3 = new Emp("853", "王一"); Emp emp4 = new Emp("125", "趙六"); Emp emp5 = new Emp("341", "黃七"); map.put(emp4.getE_id(), emp4.getE_name()); // 將物件新增到集合中 map.put(emp5.getE_id(), emp5.getE_name()); map.put(emp.getE_id(), emp.getE_name()); map.put(emp2.getE_id(), emp2.getE_name()); map.put(emp3.getE_id(), emp3.getE_name()); //Set<String> set = map.keySet(); // 獲取Map集合中的key物件集合 Iterator<String> it = map.keySet().iterator(); System.out.println("HashMap類實現的Map集合,無序:"); while (it.hasNext()) { // 遍歷Map集合 String str = (String) it.next(); String name = (String) map.get(str); System.out.println(str + " " + name); } System.out.println( ); TreeMap<String, String> treemap = new TreeMap<>(); // 建立TreeMap集合物件 treemap.putAll(map); // 向集合新增物件 Iterator<String> iter = treemap.keySet().iterator(); System.out.println("TreeMap類實現的Map集合,鍵物件升序:"); while (iter.hasNext()) { // 遍歷TreeMap集合物件 String str = (String) iter.next(); // 獲取集合中的所有key物件 String name = (String) treemap.get(str); // 獲取集合中的所有values值 System.out.println(str + " " + name); } } }
輸出結果:
HashMap類實現的Map集合,無序: 341 黃七 125 趙六 512 李四 853 王一 351 張三 TreeMap類實現的Map集合,鍵物件升序: 125 趙六 341 黃七 351 張三 512 李四 853 王一
6. 實踐練習題
- 將1~100之間的所有正整數存放在一個List集合中,並將集合中索引位置是10的物件從集合中移除。
import java.util.*; public class Text { public static void main(String[] args) { List<Integer> list = new LinkedList<>(); for(int i = 1 ;i<=100;i++){ list.add(new Integer(i)); } list.remove(list.get(10)); System.out.println("ok"); } }
輸出結果:
ok
-
分別向Set集合以及List集合中新增"A” “a” "c” "C” "a”5個元素,觀察重複值"a”能否
重複地在List集合以及Set集合中新增。
import java.util.*; public class Text { public static void main(String[] args) { Set<String> set = new HashSet<>();//HashSet是Set的子介面 set.add("a"); set.add("c"); set.add("A"); set.add("a"); set.add("C"); List<String> list = new ArrayList<>(); list.add("a"); list.add("c"); list.add("A"); list.add("a"); list.add("C"); System.out.println(set); System.out.println(list); } }
輸出結果:
[a, A, c, C] [a, c, A, a, C]
- 建立Map集合,建立Emp物件,並將Emp物件新增到集合中(Emp物件的id作為Map集合的鍵),並將id為“015”的物件從集合中移除。
首先是Emp.java:
public class Emp { private String e_id; private String e_name; public Emp( String e_id,String e_name) { this.e_id = e_id; this.e_name = e_name; } public String getE_id() { return e_id; } public void setE_id(String e_id) { this.e_id = e_id; } public String getE_name() { return e_name; } public void setE_name(String e_name) { this.e_name = e_name; } }
然後是主類:
import java.util.*; public class Text { public static void main(String[] args) { Map<String, String> map = new TreeMap<>(); Emp emp = new Emp("001", "張三"); Emp emp2 = new Emp("005", "李四"); Emp emp3 = new Emp("004", "王五"); Emp emp4 = new Emp("010", "趙六"); Emp emp5 = new Emp("015", "魏七"); map.put(emp.getE_id(), emp.getE_name()); map.put(emp2.getE_id(), emp2.getE_name()); map.put(emp3.getE_id(), emp3.getE_name()); map.put(emp4.getE_id(), emp4.getE_name()); map.put(emp5.getE_id(), emp5.getE_name()); map.remove("015"); for (String string : map.keySet()) { System.out.println(map.get(string)); } } }
輸出結果:
張三 王五 李四 趙六
參考資料:《Java從入門到精通》