Java集合框架Set&Map詳細解析
第一章 Map集合
Map 是 Java 集合框架中用于存儲鍵值對(Key-Value) 的接口,它允許通過鍵(Key)快速查找對應(yīng)的值(Value),屬于非線性集合。與 Collection 接口(存儲單元素)不同,Map 存儲的是 “鍵值對映射關(guān)系”,鍵具有唯一性(不允許重復(fù)),而值可以重復(fù)。
1.1 常見的Map集合
HashMap<K,V>:存儲數(shù)據(jù)采用的哈希表結(jié)構(gòu),元素的存取順序不能保證一致。由于要保證鍵的唯一、不重復(fù),需要重寫鍵的hashCode()方法、equals()方法。
LinkedHashMap<K,V>:HashMap下有個子類LinkedHashMap,存儲數(shù)據(jù)采用的哈希表結(jié)構(gòu)+鏈表結(jié)構(gòu)。通過鏈表結(jié)構(gòu)可以保證元素的存取順序一致;通過哈希表結(jié)構(gòu)可以保證的鍵的唯一、不重復(fù),需要重寫鍵的hashCode()方法、equals()方法。
TreeMap<K,V>:TreeMap集合和Map相比沒有特有的功能,底層的數(shù)據(jù)結(jié)構(gòu)是紅黑樹;可以對元素的鍵進行排序,排序方式有兩種:自然排序和比較器排序。
1.2 Map的常用方法
Map接口中定義了很多方法,常用的如下:
public V put(K key, V value): 把指定的鍵與指定的值添加到Map集合中。public V remove(Object key): 把指定的鍵 所對應(yīng)的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。public V get(Object key)根據(jù)指定的鍵,在Map集合中獲取對應(yīng)的值。public Set<K> keySet(): 獲取Map集合中所有的鍵,存儲到Set集合中。public Set<Map.Entry<K,V>> entrySet(): 獲取到Map集合中所有的鍵值對對象的集合(Set集合)。public boolean containKey(Object key):判斷該集合中是否有此鍵。
1.3 Map的遍歷方法
一、遍歷所有鍵(keySet())
通過 keySet() 方法獲取所有鍵的 Set 集合,再通過鍵獲取對應(yīng)的值。
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapTraversal {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("蘋果", 5);
map.put("香蕉", 3);
map.put("橙子", 7);
// 1. 遍歷所有鍵,再通過鍵獲取值
Set<String> keys = map.keySet(); // 獲取鍵的集合
for (String key : keys) {
Integer value = map.get(key); // 通過鍵獲取值
System.out.println(key + " → " + value);
}
}
}二、遍歷所有鍵值對(entrySet())
通過 entrySet() 方法獲取所有鍵值對的 Set 集合,直接從鍵值對對象中獲取鍵和值。
// 2. 遍歷所有鍵值對(推薦,效率最高)
Set<Map.Entry<String, Integer>> entries = map.entrySet(); // 獲取鍵值對集合
for (Map.Entry<String, Integer> entry : entries) {
String key = entry.getKey(); // 獲取鍵
Integer value = entry.getValue(); // 獲取值
System.out.println(key + " → " + value);
}三、遍歷所有值(values())
// 3. 僅遍歷值(無法獲取對應(yīng)鍵)
for (Integer value : map.values()) {
System.out.println("值:" + value);
}四、迭代器(Iterator)遍歷
通過迭代器遍歷 keySet() 或 entrySet(),支持在遍歷中安全刪除元素。
import java.util.Iterator;
// 4. 迭代器遍歷 entrySet(支持遍歷中刪除)
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
System.out.println(entry.getKey() + " → " + entry.getValue());
// 遍歷中刪除元素(必須用迭代器的 remove() 方法,否則拋異常)
if (entry.getValue() < 5) {
iterator.remove();
}
}1.4 HashMap的使用
HashMap 是 Java 集合框架中基于哈希表實現(xiàn)的 Map 接口實現(xiàn)類,用于存儲鍵值對(Key-Value),其特點為:
1.可以存放鍵值對
2.鍵不允許重復(fù)存放,依據(jù)是添加進來的元素的鍵 hashCode()和 equals()
3.存取順序不一致
4.允許存放null鍵、null值(鍵最多只能有一個 null)
5.線程不安全
6.JDK1.8 HashMap 采用 “數(shù)組 + 鏈表 + 紅黑樹” 的混合結(jié)構(gòu),平衡效率與哈希沖突問題
在使用上可以參考下面的代碼:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapUsage {
public static void main(String[] args) {
// 1. 初始化(指定初始容量可減少擴容次數(shù))
Map<String, Integer> scoreMap = new HashMap<>(16); // 初始容量16
// 2. 添加鍵值對
scoreMap.put("張三", 90);
scoreMap.put("李四", 85);
scoreMap.put("王五", 95);
scoreMap.put("張三", 92); // 鍵重復(fù),覆蓋舊值(張三的分數(shù)變?yōu)?2)
// 3. 獲取值
int lisiScore = scoreMap.get("李四"); // 85
System.out.println("李四的分數(shù):" + lisiScore);
// 4. 判斷是否包含鍵/值
boolean hasWangwu = scoreMap.containsKey("王五"); // true
boolean hasScore90 = scoreMap.containsValue(90); // false(已被覆蓋)
// 5. 遍歷(推薦 entrySet() 方式,效率最高)
Set<Map.Entry<String, Integer>> entries = scoreMap.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
// 6. 刪除元素
scoreMap.remove("王五"); // 刪除王五的鍵值對
// 7. 其他操作
System.out.println("元素數(shù)量:" + scoreMap.size()); // 2(張三、李四)
scoreMap.clear(); // 清空所有元素
System.out.println("是否為空:" + scoreMap.isEmpty()); // true
}
}注意:
作為鍵的對象(如自定義類)必須重寫 hashCode() 和 equals() 方法,否則會導(dǎo)致:
hashCode() 未重寫:不同對象可能計算出相同哈希值(哈希沖突加?。?,或相同對象計算出不同哈希值(無法正確查找)。
equals() 未重寫:哈希值相同的不同對象無法被識別為不同鍵(導(dǎo)致誤判為重復(fù)鍵)。
1.5 LinkedHashMap的使用
LinkedHashMap 是 HashMap 的子類,它在哈希表的基礎(chǔ)上,通過雙向鏈表維護了鍵值對的插入順序或訪問順序,兼具哈希表的高效查找能力和鏈表的有序性。
1.可以存放鍵值對
2.鍵不允許重復(fù)存放,依據(jù)是添加進來的元素的鍵 hashcode()和equals()
3.可以保證存取順序一致性,由于多了一條鏈表可以維系存進來的順序
4.允許存放null鍵、null值
5.線程不安全
LinkedHashMap 在 HashMap 的基礎(chǔ)上,給每個節(jié)點(Entry)增加了兩個指針:before(前一個節(jié)點)和 after(后一個節(jié)點),形成雙向鏈表:
參考代碼如下,比起HashMap保證了存取的一致性:
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapDemo {
public static void main(String[] args) {
Map<String, String> map = new LinkedHashMap<>();
map.put("name", "張三");
map.put("age", "20");
map.put("gender", "男");
// 遍歷順序與插入順序一致
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
// 輸出:
// name:張三
// age:20
// gender:男
}
}LinkedHashMap 是 “有序版的 HashMap”,在保留哈希表高效操作的同時,通過雙向鏈表實現(xiàn)了順序維護。
1.6TreeMap的使用
TreeMap 是 Java 集合框架中基于紅黑樹(Red-Black Tree) 實現(xiàn)的 Map 接口實現(xiàn)類,其核心特性是按鍵(Key)的自然順序或自定義順序進行排序,適合需要有序鍵值對的場景。
1.可以存放鍵值對
2.鍵不允許重復(fù)存放,依據(jù)是添加進來的元素的鍵 compareTo()返回0
3.存取順序不一致,但是會對鍵進行排序
3.1 要么元素自身具備比較性,implements Comparable, 重寫compareTo()
3.2 要么集合容器自身具備比較性,在構(gòu)造方法中,傳入Comparator比較器,重寫compare()
4.不允許存放null鍵,可以存放null值
5.線程不安全
如通過自然順序比較則代碼如下;
import java.util.TreeMap;
import java.util.Map;
public class TreeMapNaturalOrder {
public static void main(String[] args) {
// 鍵為 Integer(已實現(xiàn) Comparable,默認按數(shù)字升序排序)
TreeMap<Integer, String> numMap = new TreeMap<>();
numMap.put(3, "Three");
numMap.put(1, "One");
numMap.put(2, "Two");
numMap.put(5, "Five");
numMap.put(4, "Four");
System.out.println("按數(shù)字升序排序:");
for (Map.Entry<Integer, String> entry : numMap.entrySet()) {
System.out.println(entry.getKey() + " → " + entry.getValue());
}
// 鍵為 String(已實現(xiàn) Comparable,默認按字典序排序)
TreeMap<String, Integer> strMap = new TreeMap<>();
strMap.put("banana", 3);
strMap.put("apple", 5);
strMap.put("orange", 2);
System.out.println("\n按字符串字典序排序:");
for (Map.Entry<String, Integer> entry : strMap.entrySet()) {
System.out.println(entry.getKey() + " → " + entry.getValue());
}
}
}當(dāng)需要自定義排序規(guī)則(如降序、按字段排序等),可通過 Comparator 實現(xiàn)。
import java.util.TreeMap;
import java.util.Comparator;
import java.util.Map;
// 自定義類:Person(包含姓名和年齡)
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() { return age; }
public String getName() { return name; }
@Override
public String toString() {
return name + "(" + age + ")";
}
}
public class TreeMapCustomOrder {
public static void main(String[] args) {
// 自定義比較器:按 Person 的年齡降序排序
Comparator<Person> ageDescComparator = (p1, p2) ->
Integer.compare(p2.getAge(), p1.getAge()); // 降序(p2 - p1)
// 創(chuàng)建 TreeMap 時傳入自定義比較器
TreeMap<Person, String> map = new TreeMap<>(ageDescComparator);
map.put(new Person("張三", 20), "學(xué)生");
map.put(new Person("李四", 30), "老師");
map.put(new Person("王五", 25), "工程師");
System.out.println("按年齡降序排序:");
for (Map.Entry<Person, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " → " + entry.getValue());
}
}
}TreeMap 的核心價值在于按鍵排序和高效的范圍操作,其紅黑樹結(jié)構(gòu)保證了有序性和穩(wěn)定的性能。使用時需確保鍵可比較(通過 Comparable 或 Comparator),并注意其不支持 null 鍵和非線程安全的特性。
第二章 Set接口
java.util.Set接口和java.util.List接口一樣,同樣繼承自Collection接口,它與Collection接口中的方法基本一致,并沒有對Collection接口進行功能上的擴充,只是比Collection接口更加嚴格了。與List接口不同的是,Set接口都會以某種規(guī)則保證存入的元素不出現(xiàn)重復(fù)。
Set集合有多個子類,這里我們介紹其中的java.util.HashSet、java.util.LinkedHashSet
其實對于Set 集合本質(zhì)上可以理解為 Map 中 “鍵(Key)的集合
2.1 HashSet集合
HashSet 是 Java 集合框架中基于 HashMap 實現(xiàn)的 Set 接口實現(xiàn)類,其核心特性是存儲唯一元素(不允許重復(fù)) 且不保證元素順序,是日常開發(fā)中最常用的 Set 實現(xiàn)類之一。
使用示例:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetDemo {
public static void main(String[] args) {
// 創(chuàng)建 HashSet 實例
Set<String> set = new HashSet<>();
// 1. 添加元素(重復(fù)元素不會被添加)
set.add("apple");
set.add("banana");
set.add("apple"); // 重復(fù)元素,添加失敗
set.add(null); // 允許添加一個null
set.add(null); // 重復(fù)null,添加失敗
// 2. 遍歷元素(順序不固定)
System.out.println("增強for遍歷:");
for (String s : set) {
System.out.println(s);
}
System.out.println("\n迭代器遍歷:");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 3. 其他常用操作
System.out.println("\n是否包含banana:" + set.contains("banana")); // true
System.out.println("元素數(shù)量:" + set.size()); // 3(apple、banana、null)
set.remove("banana"); // 刪除元素
System.out.println("刪除后元素:" + set); // [null, apple](順序可能不同)
set.clear(); // 清空集合
System.out.println("清空后是否為空:" + set.isEmpty()); // true
}
}當(dāng)自定義類作為 HashSet 元素時,必須同時重寫 hashCode() 和 equals() 方法,否則會導(dǎo)致重復(fù)元素?zé)o法被識別。
2.2 LinkedHashSet集合
LinkedHashSet 是 HashSet 的子類,底層基于 LinkedHashMap 實現(xiàn),它在保證元素唯一性的同時,還能維護元素的插入順序,兼具 HashSet 的高效性和鏈表的有序性。
使用示例:
import java.util.LinkedHashSet;
import java.util.Set;
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
// 添加元素(重復(fù)元素不生效)
set.add("張三");
set.add("李四");
set.add("王五");
set.add("張三"); // 重復(fù),不添加
// 遍歷順序與插入順序一致
System.out.println("遍歷元素:");
for (String name : set) {
System.out.println(name);
}
// 其他操作(與 HashSet 一致)
System.out.println("\n是否包含李四:" + set.contains("李四")); // true
set.remove("王五");
System.out.println("刪除后元素:" + set); // [張三, 李四]
}
}2.3 TreeSet集合
TreeSet 是 Java 集合框架中基于 TreeMap 實現(xiàn)的 Set 接口實現(xiàn)類,其核心特性是元素唯一且有序,排序規(guī)則基于元素的自然順序或自定義比較器,適合需要對元素進行排序和去重的場景。
1. 自然排序
元素類型需實現(xiàn) java.lang.Comparable 接口,并重寫 compareTo() 方法定義排序規(guī)則(如 Integer、String 等內(nèi)置類已實現(xiàn))。
import java.util.TreeSet;
import java.util.Set;
public class TreeSetNaturalSort {
public static void main(String[] args) {
// 元素為 Integer(已實現(xiàn) Comparable,默認按數(shù)字升序)
Set<Integer> set = new TreeSet<>();
set.add(3);
set.add(1);
set.add(2);
set.add(3); // 重復(fù)元素,不添加
System.out.println("自然排序(升序):" + set); // [1, 2, 3]
}
}2. 自定義排序
創(chuàng)建 TreeSet 時傳入 java.util.Comparator 接口實現(xiàn)類,指定自定義排序規(guī)則(如降序、按對象字段排序)。
import java.util.TreeSet;
import java.util.Comparator;
public class TreeSetCustomSort {
public static void main(String[] args) {
// 自定義比較器:按整數(shù)降序
Comparator<Integer> descComparator = Comparator.reverseOrder();
TreeSet<Integer> set = new TreeSet<>(descComparator);
set.add(3);
set.add(1);
set.add(2);
System.out.println("自定義排序(降序):" + set); // [3, 2, 1]
}
}到此這篇關(guān)于Java集合框架Set&Map的文章就介紹到這了,更多相關(guān)java集合框架set map內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
一文快速了解spring?boot中的@idempotent注解
idempotence注解是RESTful API設(shè)計中一個重要的概念,它可以保證操作的可靠性和一致性,下面這篇文章主要給大家介紹了關(guān)于spring?boot中@idempotent注解的相關(guān)資料,需要的朋友可以參考下2024-01-01
Java的可變參數(shù)與Collections類的功能示例解析
這篇文章主要為大家介紹了Java的可變參數(shù)與Collections類的功能示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
java構(gòu)造函數(shù)的三種類型總結(jié)
在本篇文章里小編給大家整理了一篇關(guān)于java構(gòu)造函數(shù)的三種類型總結(jié)內(nèi)容,有需要的朋友們可以學(xué)習(xí)參考下。2021-01-01

