Map
是Java集合框架中的一个重要接口,它代表了一个键值对(key-value)映射,其中每个键(key)对应一个值(value)。Map
接口不继承Collection
接口,因此它与List
、Set
等集合类不同。常用的Map
实现类包括HashMap
、TreeMap
、LinkedHashMap
、Hashtable
等。
1. Map的常见实现类
HashMap
:
HashMap
是最常用的Map
实现类,底层使用哈希表来存储键值对。- 它允许
null
键和null
值。 - 不保证键值对的顺序,即不保证遍历时的顺序。
LinkedHashMap
:
LinkedHashMap
是HashMap
的一个变种,除了维护哈希表外,还使用链表来维护元素的插入顺序。- 它可以按照插入顺序遍历元素,也可以按照访问顺序遍历(通过构造函数设置)。
TreeMap
:
TreeMap
基于红黑树实现,自动按键的自然顺序或指定的比较器顺序排序。- 不允许
null
键,但允许null
值。
Hashtable
:
Hashtable
是一个早期的Map
实现类,基本上和HashMap
相似,但它是线程安全的,性能较低。- 不允许
null
键和null
值。
2. Map接口的常用方法
put(K key, V value)
:将指定的值与指定的键关联,如果键已经存在,返回旧值,并替换它。get(Object key)
:根据指定的键获取对应的值,如果不存在则返回null
。remove(Object key)
:移除指定的键值对。containsKey(Object key)
:检查Map中是否包含指定的键。containsValue(Object value)
:检查Map中是否包含指定的值。size()
:返回Map中的键值对数量。keySet()
:返回Map中所有键的集合。values()
:返回Map中所有值的集合。entrySet()
:返回Map中所有键值对的Set
集合。
3. 示例代码:
示例 1:使用HashMap
存储和获取数据
import java.util.*;
public class MapExample {
public static void main(String[] args) {
// 创建一个HashMap
Map<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 35);
// 获取值
System.out.println("Alice's age: " + map.get("Alice"));
// 检查键是否存在
if (map.containsKey("Bob")) {
System.out.println("Bob's age: " + map.get("Bob"));
}
// 遍历Map中的所有键值对
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 删除键值对
map.remove("Charlie");
// 获取Map的大小
System.out.println("Map size: " + map.size());
}
}
输出:
Alice's age: 25
Bob's age: 30
Alice: 25
Bob: 30
Map size: 2
示例 2:使用LinkedHashMap
保持插入顺序
import java.util.*;
public class LinkedHashMapExample {
public static void main(String[] args) {
Map<String, Integer> map = new LinkedHashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 35);
// 遍历Map时按插入顺序输出
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
输出:
Alice: 25
Bob: 30
Charlie: 35
示例 3:使用TreeMap
按键的自然顺序排序
import java.util.*;
public class TreeMapExample {
public static void main(String[] args) {
Map<String, Integer> map = new TreeMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 35);
// 遍历Map时按键的自然顺序输出
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
输出:
Alice: 25
Bob: 30
Charlie: 35
示例 4:使用Map
的一些其他方法
import java.util.*;
public class MapMethodsExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
map.put("Charlie", 35);
// 使用 containsKey 和 containsValue
System.out.println("Contains key 'Alice': " + map.containsKey("Alice"));
System.out.println("Contains value 30: " + map.containsValue(30));
// 使用 keySet 获取所有键
Set<String> keys = map.keySet();
System.out.println("Keys: " + keys);
// 使用 values 获取所有值
Collection<Integer> values = map.values();
System.out.println("Values: " + values);
// 使用 entrySet 获取所有键值对
Set<Map.Entry<String, Integer>> entries = map.entrySet();
System.out.println("Entries: " + entries);
}
}
输出:
Contains key 'Alice': true
Contains value 30: true
Keys: [Alice, Bob, Charlie]
Values: [25, 30, 35]
Entries: [Alice=25, Bob=30, Charlie=35]
4. 常见应用场景
- 存储配置:
Map
非常适合用来存储配置项,其中键是配置项的名称,值是对应的配置值。 - 频次统计:例如,统计一个文本中每个单词出现的次数,可以使用
Map<String, Integer>
。 - 缓存实现:
Map
可以用来实现缓存,其中键是缓存的标识符,值是缓存的内容。
5. 线程安全
HashMap
本身不是线程安全的。如果需要线程安全的Map
,可以使用:
Collections.synchronizedMap()
:将普通的Map
包装成线程安全的Map
。ConcurrentHashMap
:它是一个线程安全的Map
实现,适用于高并发环境。