目录
- 前言
- Map实现类
- 常用方法
- 特殊用法
- WeakHashMap
- LinkedHashMap
- EnumMap
前言
什么是Map:
Map
集合是Java中一种用于存储键值对的数据结构。它提供了一种将键映射到值的方式,每个键对应一个唯一的值。Map
中的键是唯一的,但值可以重复。
在Map
中,可以通过键来快速检索对应的值,这使得Map
非常适合处理需要根据给定的键来查找、更新和删除相关值的情况。例如,可以使用学生的学号作为键,将学生的信息作为值进行存储。
Map
接口是Java中定义Map集合的顶级接口,它提供了一系列操作Map的方法。常用的Map实现类有HashMap、TreeMap和LinkedHashMap
等。这些具体的实现类基于不同的数据结构,在性能和特性方面有所差异,可以根据需求选择适合的实现类。
总和来说,Map
集合是一种存储键值对的数据结构,通过键来快速访问和操作对应的值。它提供了丰富的方法来增加、删除、修改和查询键值对,是Java中常用的数据结构之一。
Map的常见用途包括:
数据的存储和检索
:Map可以用来存储大量的数据,并通过键来快速查找对应的值,例如将学生的学号映射到他们的成绩上。缓存机制
:Map可以用作缓存的数据结构,将计算结果或者重要的数据存储在其中,以便后续使用。这样可以避免重复计算或者频繁地进行IO操作。统计信息
:Map可以用于统计某些数据的数量或者频率,例如统计一段文本中每个单词出现的次数。
Map实现类
HashMap
:HashMap是基于哈希表的Map实现类,它通过哈希函数将键映射到存储位置。它提供了快速插入、查找和删除操作,并且不保证元素的顺序。TreeMap
:TreeMap是基于红黑树的有序Map实现类,它会对键进行排序并保持有序状态。TreeMap具有按照键的自然顺序或者自定义顺序来访问键值对的能力。LinkedHashMap
:LinkedHashMap基于哈希表和双向链表的Map实现类,它保留了元素插入的顺序。LinkedHashMap可以用作LRU(最近最少使用)缓存,以便在缓存满时移除最不常访问的元素。EnumMap
:EnumMap是专门用于枚举类型键的Map实现类,它要求所有的键都必须属于同一个枚举类型。EnumMap内部使用数组实现,因此其性能高效。WeakHashMap
:WeakHashMap是一种特殊的Map实现类,它的键是弱引用(WeakReference),在没有其他强引用指向键时,可以被垃圾回收器回收。
常用方法
以下是常用的使用方法,以HashMap
为:
- put(key, value)
向Map中添加一个键值对,如果该键已存在,则会替换旧的值。Map<String, Integer> map = new HashMap<>(); map.put("A", 25); map.put("B", 30); map.put("C", 28);
- get(key)
根据给定的键获取对应的值。int aliceAge = map.get("Alice"); System.out.println("Alice的年龄是:" + aliceAge);
- containsKey(key)
判断Map中是否包含指定的键。boolean containsA = map.containsKey("A"); System.out.println("是否包含A:" + containsA );
- containsValue(value)
判断Map中是否包含指定的值。boolean containsAge30 = map.containsValue(30); System.out.println("是否包含30:" + containsAge30);
- remove(key)
根据给定的键删除对应的键值对。
map.remove("B");
-
size()
返回Map中键值对的数量。int size = map.size(); System.out.println("Map中的键值对数量:" + size);
-
isEmpty()
判断Map是否为空。boolean empty = map.isEmpty(); System.out.println("Map是否为空:" + empty);
-
keySet()
返回Map中所有键的集合。Set<String> keys = map.keySet(); for (String key : keys) { System.out.println("键:" + key); }
-
values()
返回Map中所有值的集合。Collection<Integer> values = map.values(); for (int value : values) { System.out.println("值:" + value); }
-
entrySet()
返回Map中所有键值对的集合,进行遍历Map。Set<Map.Entry<String, Integer>> entries = map.entrySet(); for (Map.Entry<String, Integer> entry : entries) { String key = entry.getKey(); int value = entry.getValue(); System.out.println("键:" + key + ",值:" + value); }
-
clear():
清空Map,移除所有的键值对。map.clear();
-
putAll(map):
将另一个Map的键值对全部添加到当前Map中。Map<String, Integer> anotherMap = new HashMap<>(); anotherMap.put("D", 35); anotherMap.put("E", 32); map.putAll(anotherMap);
-
getOrDefault(key, defaultValue)
根据给定的键获取对应的值,如果键不存在,则这只一个默认值并且返回。int h = map.getOrDefault("H", 0); System.out.println("H的值是:" + h);
-
forEach遍历
map.forEach((k,v) -> { System.out.println("键:" + key + ",值:" + value); });
高级用法:
-
merge
merge
方法用于将指定的键和值合并到该映射中。如果指定键不存在,则会直接添加键值对,如果存在,则会使用提供的合并函数对已有的值进行修改。合并函数是一个函数式接口(对新值与旧值进行数据处理),接收两个参数:旧值和新值,并返回合并后的值。示例:
Map<String, Integer> map = new HashMap<>(); map.put("A", 1); map.merge("A", 2, (oldValue, newValue) -> oldValue + newValue); // 结果为:3,A已经存在,返回1+2=3 map.merge("B", 2, (oldValue, newValue) -> oldValue * newValue); // 结果为:2,B不存在,直接返回2
-
putIfAbsent
putIfAbsent
方法用于将指定键值对添加到映射中,但仅在指定的键当前没有对应值时执行。如果键存在,则不做任何更改,并返回已存在的值;如果键不存在,则添加键值对,并返回 null。示例:
Map<String, Integer> map = new HashMap<>(); map.put("A", 1); map.putIfAbsent("A", 2); // 结果为:1,因为A已存在 map.putIfAbsent("B", 2); // 结果为:2,因为B已存在,map中新增B
特殊用法
WeakHashMap
WeakHashMap
是 Java 中的一个特殊类型的哈希映射。它与HashMap
类似,但具有不同的垃圾回收行为。
它的键(key)是弱引用,这意味着当没有对键的强引用存在时,垃圾回收器会自动回收该键所占用的内存空间。而在普通的 HashMap
中,如果键仍然存在于映射中,即使没有对键的引用,垃圾回收器也不会回收其所占用的内存。
这使得 WeakHashMap
特别适合用于缓存和临时映射,因为它允许垃圾回收器根据内存需求自动清除不再需要的映射项。
示例:
import java.util.WeakHashMap;
public class WeakHashMapExample {
public static void main(String[] args) {
WeakHashMap<String, Integer> map = new WeakHashMap<>();
String key1 = new String("Key 1"); // 创建一个新的字符串对象作为键
String key2 = new String("Key 2");
map.put(key1, 10);
map.put(key2, 20);
System.out.println(map); // 输出: {Key 2=20, Key 1=10}
key1 = null; // 解除对 key1 的强引用
System.gc(); // 运行垃圾回收器
System.out.println(map); // 输出: {Key 2=20}
}
}
LinkedHashMap
LinkedHashMap
是 Java 中的一个特殊类型的哈希映射,它扩展了 HashMap
并提供了有序的插入顺序。
与普通的 HashMap
不同,LinkedHashMap
在内部使用一个双向链表来维护插入顺序。这意味着当遍历 LinkedHashMap
时,元素将按照插入的顺序进行迭代。而在普通的 HashMap
中,元素的顺序是不确定的。
示例:
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapExample {
public static void main(String[] args) {
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("Key 1", 10);
map.put("Key 2", 20);
map.put("Key 3", 30);
// 遍历 LinkedHashMap 输出键和值
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
}
}
结果:
Key 1 -> 10
Key 2 -> 20
Key 3 -> 30
LinkedHashMap
还提供了构造函数,允许指定排序模式。排序模式可以是按照插入顺序(默认)、访问顺序或自定义的排序方式。
使用按照访问顺序排序的 LinkedHashMap:
当一个key被访问后,那么将会被移动最后一位。
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapExample {
public static void main(String[] args) {
LinkedHashMap<String, Integer> map = new LinkedHashMap<>(16, 0.75f, true);
map.put("Key 1", 10);
map.put("Key 2", 20);
map.put("Key 3", 30);
// 访问 Key 2,将其移到链表尾部
map.get("Key 2");
// 遍历 LinkedHashMap 输出键和值,按照访问顺序排序
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " -> " + entry.getValue());
}
}
}
结果:
Key 1 -> 10
Key 3 -> 30
Key 2 -> 20
通过设置 LinkedHashMap
的构造函数中的第三个参数为true
,我们启用了按照访问顺序进行排序。当我们访问元素 "Key 2"
时,它被移到了链表的尾部,因此在遍历时它显示在最后。
EnumMap
EnumMap
是 Java 中的一种特殊的映射实现,它要求键是枚举类型。EnumMap
在内部使用数组来表示键值对,并且根据枚举常量的顺序进行了优化,因此具有较高的性能。
示例:
import java.util.EnumMap;
import java.util.Map;
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class EnumMapExample {
public static void main(String[] args) {
EnumMap<Day, String> schedule = new EnumMap<>(Day.class);
schedule.put(Day.MONDAY, "MONDAY_VALUE");
schedule.put(Day.TUESDAY, "TUESDAY_VALUE");
schedule.put(Day.WEDNESDAY, "WEDNESDAY_VALUE");
// 遍历 EnumMap 输出键和值
for (Map.Entry<Day, String> entry : schedule.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
结果:
创建了一个 EnumMap
并向其添加了几个键值对。这里的键是枚举类型 Day,而值是字符串类型。然后我们通过遍历 EnumMap
来输出所有的键和值。
需要注意的是,由于 EnumMap 要求键是枚举类型,因此只能使用具有确定值集的枚举类作为键的类型。
MONDAY: "MONDAY_VALUE"
TUESDAY: "TUESDAY_VALUE"
WEDNESDAY: "WEDNESDAY_VALUE"