Java 集合
文章目錄
1. 集合基本概念
集合表示一組對象,每個對象被稱爲其元素。一些集合允許重複的元素,而另一些則不允許。一些是有序的,而其他則是無序的。
2. 集合與數組的區別
區別 | 元素類型 | 元素個數 |
---|---|---|
數組 | 基本類型、引用類型 | 固定,不能任意擴展 |
集合 | 引用類型(存儲基本類型時自動裝箱) | 不固定,可任意擴展 |
集合的優點:
- 不受容器大小限制,可以隨時添加、刪除元素。
- 提供了大量操作元素的方法(判斷、獲取等)。
3. 泛型
泛型,顧名思義指的是任意類型,又叫參數化類型(ParameterizedType),對具體類型的使用起到輔助作用,類似於方法參數。
3.1 集合類泛型
表示該集合中存放指定類型的元素,例如:
List<String> list = new ArrayList<>() 。
3.2 泛型好處
- 泛化:可以用T代表任意類型。
- 類型安全:使用泛型可以使編譯器知道變量的類型限制,進而可以在更高程度上驗證類型假設。
- 消除強制類型轉換:使代碼更加可讀,並減少出錯的機會。
注意:
- 泛型一般只會和集合類結合使用。
- 泛型是JDK5的新特性,從JDK7開始,右邊的泛型可以不用寫具體的數據類型了。(菱形泛型)
應用舉例:
//指定集合中的元素時 String 類型
List<String> list2 = new ArrayList<>();
list2.add("abc");
list2.add("bcd");
list2.add("cde");
//2. 遍歷集合:增強 for
for (String str : list2) {
System.out.println(str);
}
4. 迭代器(Iterator)
迭代器是遍歷Collection集合的通用方式,可以在對集合遍歷的同時進行添加、刪除等操作。
4.1 迭代器中的方法
方法名 | 描述 |
---|---|
boolean hasNext() | 如果還有可迭代元素,則返回true。 |
E next() | 返回迭代中的下一個元素對象。 |
default void remove() | 從基礎集合中移除此迭代器返回的最後一個元素(可選操作)。 |
應用演示:
// list 集合對象
List list = new ArrayList();
//使用迭代器遍歷 list 集合
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
//使用增強 for 來遍歷 list 集合
for (Object object: list){
System.out.println(object);
}
5. Collections 接口
Collection 是最基本的集合接口,一個 Collection 代表一組 Object,即 Collection 的元素, Java不提供直接繼承自Collection的類,只提供繼承於的子接口(如List和set)。
5.1 Collections中常用方法
方法名 | 描述 |
---|---|
sort(List list) | 根據其元素的自然順序,將指定列表按升序 排序。 |
max(Collection<? extends T> coll) | 根據其元素的自然順序返回給定集合的最大元素。 |
reverse(List<?> list) | 反轉指定列表中元素的順序。 |
shuffle(List<?> list) | 使用默認的隨機性源隨機排列指定的列表。 |
實例演示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* 演示Collections類
*/
public class Test {
public static void main(String[] args) {
//創建集合對象
List<Integer> list = new ArrayList<>();
//添加元素
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(4);
list.add(3);
list.add(2);
list.add(1);
//打印集合
System.out.println(list);
System.out.println("---------------------分割線-------------------------");
//max()方法:獲取最大元素
Integer max = Collections.max(list);
System.out.println("集合中最大的元素爲:"+max);
System.out.println("---------------------分割線-------------------------");
//sort();按升序排序
Collections.sort(list);
System.out.println("升序排列後的結果爲:"+list);
System.out.println("---------------------分割線-------------------------");
//reverse():對集合中的數據進行翻轉
Collections.reverse(list);
System.out.println("反轉以後的數據爲:"+list);
//降序排序==升序排序+反轉
System.out.println("---------------------分割線-------------------------");
//shuffle():隨機置換
Collections.shuffle(list);
System.out.println("隨機置換後的數據:" + list);
}
}
運行結果:
[1, 2, 3, 4, 5, 4, 3, 2, 1]
---------------------分割線-------------------------
集合中最大的元素爲:5
---------------------分割線-------------------------
升序排列後的結果爲:[1, 1, 2, 2, 3, 3, 4, 4, 5]
---------------------分割線-------------------------
反轉以後的數據爲:[5, 4, 4, 3, 3, 2, 2, 1, 1]
隨機置換後的數據:[2, 1, 4, 1, 5, 3, 3, 2, 4]
6. List 接口
List 接口是一個有序的 Collection,使用此接口能夠精確的控制每個元素插入的位置,能夠通過索引(元素在 List 中位置,類似於數組的下標)來訪問List中的元素,第一個元素的索引爲 0,而且允許有相同的元素。
List是單列集合,具有重複性、有序(存取順序相同)等特點。
6.1 List 接口中常用方法
方法名 | 描述 |
---|---|
void add(int index, E element) | 將指定的元素插入此列表中的指定位置。 |
boolean add(E e) | 將指定的元素追加到此列表的末尾。 |
E get(int index) | 返回此列表中指定位置的元素。 |
int size() | 返回此列表中的元素數。 |
實例演示:
- 定義一個標準類:學生類
/**
* 標準類:學生類
* 屬性:name,age
*/
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 定義測試類
import java.util.ArrayList;
import java.util.List;
/**
* 演示List操作
*/
public class Test {
public static void main(String[] args) {
//創建集合對象和學生對象
List list = new ArrayList();
Student s1 = new Student("劉備", 40);
Student s2 = new Student("劉備", 40);
Student s3 = new Student("關羽", 39);
Student s4 = new Student("張飛", 37);
//添加到集合
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
//直接打印集合
System.out.println(list);
System.out.println("----------------------分割線---------------------");
//獲取索引爲2的元素
Object obj = list.get(2);
System.out.println(obj);
//獲取集合中的元素個數
System.out.println("集合長度爲:" + list.size());
System.out.println("----------------------分割線---------------------");
//遍歷集合
for (int i = 0; i < list.size(); i++) {
Object obj2 = list.get(i);
System.out.println("索引爲 " + i + " 的元素時" + obj2);
}
}
}
運行結果:
[Student{name='劉備', age=40}, Student{name='劉備', age=40}, Student{name='關羽', age=39}, Student{name='張飛', age=37}]
----------------------分割線---------------------
Student{name='關羽', age=39}
集合長度爲:4
----------------------分割線---------------------
索引爲 0 的元素時Student{name='劉備', age=40}
索引爲 1 的元素時Student{name='劉備', age=40}
索引爲 2 的元素時Student{name='關羽', age=39}
索引爲 3 的元素時Student{name='張飛', age=37}
7. Set 接口
Set 具有與 Collection 完全一樣的接口,只是行爲上不同,Set 不保存重複的元素。
Set 接口存儲一組唯一,無序的對象。
案例演示:
- 在上面Student類的基礎上加上equals()和hashCode()兩個方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
- 編寫定義測試類
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Set集合演示
*/
public class Test {
public static void main(String[] args) {
//創建集合對象
Set<Student> set = new HashSet<>();
//創建元素對象
Student s1 = new Student("趙雲",20);
Student s2 = new Student("關羽",26);
Student s3 = new Student("張飛",24);
Student s4 = new Student("馬超",23);
Student s5 = new Student("黃忠",28);
Student s6 = new Student("黃忠",28);
//添加
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
set.add(s5);
set.add(s6);
//打印整個集合
System.out.println(set);
/**
* Set集合保證元素的唯一性依賴:equals()和hashCode()兩個方法
* 需要在Student中重寫這兩個方法
*/
System.out.println("通過迭代器遍歷集合:");
Iterator<Student> it = set.iterator();
//判斷迭代器中是否有元素
while(it.hasNext()){
Student s = it.next();
System.out.println(s);
}
System.out.println("----------------------分割線-----------------------");
System.out.println("通過增強for遍歷集合:");
for (Student student : set) {
System.out.println(student);
}
}
}
[Student{name='關羽', age=26}, Student{name='趙雲', age=20}, Student{name='馬超', age=23}, Student{name='張飛', age=24}, Student{name='黃忠', age=28}]
----------------------分割線-----------------------
通過迭代器遍歷集合:
Student{name='關羽', age=26}
Student{name='趙雲', age=20}
Student{name='馬超', age=23}
Student{name='張飛', age=24}
Student{name='黃忠', age=28}
----------------------分割線-----------------------
通過增強for遍歷集合:
Student{name='關羽', age=26}
Student{name='趙雲', age=20}
Student{name='馬超', age=23}
Student{name='張飛', age=24}
Student{name='黃忠', age=28}
注意:
- Set 保證元素的唯一性依賴於 equals() 和 hashCode() 兩個方法。
- Set 的成員方法與List相同。
8. Map 接口
Map 接口存儲一組鍵值對象,將鍵映射到值的對象。映射不能包含重複的鍵;每個鍵最多可以映射到一個值。
應用:
Map<T1,T2> map = new HashMap<>();
泛型參數:
- T1表示鍵的類型
- T2表示值的類型
8.1 常用方法
方法名 | 描述 |
---|---|
V put(K key, V value) | 向集合中添加鍵值對元素,第一次添加,返回null對象,如果添加的鍵已存在,會用新值覆蓋舊值,並返回舊值對象 |
V get(Object key) | 返回指定鍵所映射的值。 |
Set keySet() | 獲取所有鍵的集合。 |
應用演示:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 演示 Map 集合
*/
public class Test {
public static void main(String[] args) {
//1.創建集合對象,鍵爲int型,值爲Student對象。
Map<Integer, Student> map = new HashMap<>();
//2.創建元素對象
Student s1 = new Student("劉備", 44);
Student s2 = new Student("關羽", 43);
Student s3 = new Student("張飛", 42);
/**
* put()方法演示
* 對應鍵插值
*/
Student stu1 = map.put(1, s1);
System.out.println("第一次添加:" + stu1);
Student stu2 = map.put(1, s2);
System.out.println("第二次添加,同鍵異值:" + stu2);
Student stu3 = map.put(1, s2);
System.out.println("第三次添加,同鍵同值:" + stu3);
System.out.println("-----------------------分割線------------------------");
/**
* get()方法演示:根據鍵取值
*/
map.put(1, s1);
map.put(2, s2);
map.put(3, s3);
Student stu4 = map.get(1);
Student stu5 = map.get(2);
Student stu6 = map.get(3);
System.out.println(stu4);
System.out.println(stu5);
System.out.println(stu6);
System.out.println("-----------------------分割線------------------------");
/**
* 遍歷集合
* 迭代器,增強for
*/
//4 迭代器
//4.1 獲取所有鍵的集合,keySet()
Set<Integer> keys = map.keySet();
//4.2 遍歷所有鍵,獲取到每一個鍵。
Iterator<Integer> it = keys.iterator(); //創建迭代器對象
while (it.hasNext()) {
//4.3 獲取迭代器中的鍵
Integer key = it.next();
//4.4 根據鍵,獲取映射的值。
Student value = map.get(key);
//4.5 打印
System.out.println("key:" + key + "...value:" + value);
}
System.out.println("-----------------------分割線------------------------");
//增強for
//獲取所有鍵
Set<Integer> keys2 = map.keySet();
for (Integer key : keys2) {
//獲取所有鍵映射的值
Student value = map.get(key);
System.out.println("key:" + key + "...value:" + value);
}
}
}
運行結果:
第一次添加:null
第二次添加,同鍵異值:Student{name='劉備', age=44}
第三次添加,同鍵同值:Student{name='關羽', age=43}
-----------------------分割線------------------------
Student{name='劉備', age=44}
Student{name='關羽', age=43}
Student{name='張飛', age=42}
-----------------------分割線------------------------
key:1...value:Student{name='劉備', age=44}
key:2...value:Student{name='關羽', age=43}
key:3...value:Student{name='張飛', age=42}
-----------------------分割線------------------------
key:1...value:Student{name='劉備', age=44}
key:2...value:Student{name='關羽', age=43}
key:3...value:Student{name='張飛', age=42}