Java Map集合的用法(非常详细)
在 Java 开发中,Map 集合的使用也是比较广泛的。Map 集合以键值对方式存储数据,键和值一一对应,通过键可以获取值,并且键不能重复。
Map 接口的常用实现类有 HashMap、TreeMap、Properties,本节将详细讲解 Map 接口的使用。
Map 集合本身由键(key)的集合和值(value)的集合构成:
这里给出 Map 接口的常用方法,如下表所示:
HashMap 判断两个键是否相同的规则与 HashSet 类似,也是先通过 hashCode() 方法判断键的哈希值是否相同,再通过 equals() 方法判断键的数据是否相等。
HashMap 内部结构和数据存储过程如下图所示:

图 1 HashMap 内部结构和数据存储过程
根据图 1 所示,HashMap 的内部结构是由数组和链表构成的。当向 HashMap 中添加键值对数据时,会先使用键的 hashCode() 方法得到一个哈希值。这个哈希值对应一个集合中的存储位置:
接下来,通过案例来演示 HashMap 集合的使用:
HashMap 中的键是不可重复的,因为键是用 Set 集合存储的。接下来,通过案例来演示 HashMap 的键重复时的情况:
接下来,通过案例来演示 TreeMap 集合的具体用法:
运行之后,结果中可以看到集合中元素顺序并不是这样,而是按键值的大小来升序排列的,这是因为 String 实现了 Comparable 接口,所以默认会按照自然顺序进行排序。
TreeMap 除了可以使用自然顺序进行排序外,还支持定制排序,可以根据自己的需求实现排序逻辑。接下来,通过案例来演示在 TreeMap 集合中实现定制排序:
Hashtable 类因为要确保线程安全,所以存取元素速度比较慢,目前用的比较少。不过它的子类 Properties 在实际开发中用的比较多,该子类对象主要用于处理 properties 属性文件,由于属性文件里的键和值都是字符串类型,所以 Properties 集合里的键和值都是字符串类型。
这里给出 Properties 类的常用方法,如下表所示:
接下来,通过案例来演示 Properties 类的用法:
Map 接口的常用实现类有 HashMap、TreeMap、Properties,本节将详细讲解 Map 接口的使用。
Java Map接口简介
Map 接口与 Collection 接口是并列存在的,它以键值对(key-value)的形式存储元素,可以按照键访问值。Map 集合本身由键(key)的集合和值(value)的集合构成:
- 键的集合是 Set 集合,因此不能有重复的元素,当向 Map 中添加已有的键时,则新的键会覆盖已有的键,通常用 String 类作为 Map 的 key;
- 值的集合是 Collection 集合,可以存在重复元素。Map 中键和值是成对出现的,即通过指定的 key 总能找到唯一与之对应的 value。
这里给出 Map 接口的常用方法,如下表所示:
| 方法 | 方法描述 |
|---|---|
| Object put(Object key, Object value) | 以键值对的方式向集合添加数据 |
| Object remove(Object key) | 以键为参数删除集合中的键值对数据 |
| void putAll(Map t) | 将其他 Map 中的数据添加到当前 Map 集合中 |
| void clear() | 清除当前 Map 中的所有数据 |
| Object get(Object key) | 根据键获取对应的值,找不到则返回 null |
| boolean containsKey(Object key) | 判断集合中是否包含对应的键,包含则返回 true |
| boolean containsValue(Object value) | 判断集合中是否包含对应的值,包含则返回 true |
| int size() | 返回集合中的记录数 |
| boolean isEmpty() | 判断集合是否为空的,空则返回 true |
| Set keySet() | 返回集合中键的 Set 视图 |
| Collection values() | 返回集合中值的 Collection 视图 |
| Set entrySet() | 返回集合中的键值对的 Set 视图 |
Java HashMap集合
HashMap 类是 Map 接口中使用最多的实现类,它的键和值允许为 null。因为它的键也是使用哈希算法进行存储的,所以与 HashSet 集合一样,不保证数据的顺序,另外键也不允许重复。HashMap 判断两个键是否相同的规则与 HashSet 类似,也是先通过 hashCode() 方法判断键的哈希值是否相同,再通过 equals() 方法判断键的数据是否相等。
HashMap 内部结构和数据存储过程如下图所示:

图 1 HashMap 内部结构和数据存储过程
根据图 1 所示,HashMap 的内部结构是由数组和链表构成的。当向 HashMap 中添加键值对数据时,会先使用键的 hashCode() 方法得到一个哈希值。这个哈希值对应一个集合中的存储位置:
- 如果对应的位置上没有元素,则键值对数据可以直接存到这个位置上。
- 如果对应的位置上有数据,则会调用键的 equals() 方法和这个位置上存储的所有元素的键比较一下:
- 如果没有相同的键,则键值对数据会被添加到这个位置上的链表结构中;
- 如果有相同的键,则新添加的键值对数据会覆盖旧的键值对数据。
接下来,通过案例来演示 HashMap 集合的使用:
import java.util.*;
public class Demo {
public static void main(String[] args) {
Map map = new HashMap(); // 创建HashMap集合
map.put(null, null); // 存入键值对,键和值都为null
map.put("car1", "布加迪"); // 存入非空数据
map.put("car2", "保时捷");
map.put("car3", "兰博基尼");
System.out.println(map.size()); // 打印集合长度
System.out.println(map); // 打印集合所有元素
System.out.println(map.get("car3")); // 取出并打印键为car3的值
}
}
程序的运行结果如下:
4
{null=null, car2=保时捷, car3=兰博基尼, car1=布加迪}
兰博基尼
HashMap 中的键是不可重复的,因为键是用 Set 集合存储的。接下来,通过案例来演示 HashMap 的键重复时的情况:
import java.util.*;
public class Demo {
public static void main(String[] args) { // 创建HashMap集合
Map map = new HashMap(); // 存入元素
map.put("car1", "布加迪");
map.put("car2", "保时捷");
map.put("car3", "兰博基尼");
map.put("car3", "劳斯莱斯"); // 存入重复的键car3
System.out.println(map); // 打印集合所有元素
}
}
程序的运行结果如下:
{car2=保时捷, car3=劳斯莱斯, car1=布加迪}
以上代码中,键“car3”被添加了两次,第 1 次“car3”值为“兰博基尼”,第 2 次“car3”值为“劳斯莱斯”,当键被重复添加时,后添加的键值覆盖了前面添加的键值。Java TreeMap集合
TreeMap 类也是 Map 接口的一个常用的实现类。TreeMap 集合存储键值对时,会根据键进行排序。该集合可以保证所有的键值对都处于有序状态。接下来,通过案例来演示 TreeMap 集合的具体用法:
import java.util.*;
public class Demo {
public static void main(String[] args) {
Map map = new TreeMap(); // 创建TreeMap集合
map.put("Girl3", "西施"); // 添加元素
map.put("Girl2", "王昭君");
map.put("Girl1", "貂蝉");
map.put("Girl4", "杨玉环");
Iterator iterator = map.keySet().iterator(); // 获取迭代器对象
while (iterator.hasNext()) {
Object key = iterator.next(); // 取到键
Object value = map.get(key); // 取到值
System.out.println(key + ":" + value);
}
}
}
程序的运行结果如下:
Girl1:貂蝉
Girl2:王昭君
Girl3:西施
Girl4:杨玉环
运行之后,结果中可以看到集合中元素顺序并不是这样,而是按键值的大小来升序排列的,这是因为 String 实现了 Comparable 接口,所以默认会按照自然顺序进行排序。
TreeMap 除了可以使用自然顺序进行排序外,还支持定制排序,可以根据自己的需求实现排序逻辑。接下来,通过案例来演示在 TreeMap 集合中实现定制排序:
import java.util.*;
public class Demo {
public static void main(String[] args) {
// 创建TreeMap集合并传入一个实现了Comparator接口的自定义对象
Map map = new TreeMap(new TestComparator()); // 添加元素
map.put("Girl3", "西施");
map.put("Girl2", "王昭君");
map.put("Girl1", "貂蝉");
map.put("Girl4", "杨玉环");
// 获取迭代器对象
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Object key = iterator.next(); // 取到键
Object value = map.get(key); // 取到值
System.out.println(key + ":" + value);
}
}
}
class TestComparator implements Comparator { // 自定义类,实现Comparator接口
public int compare(Object o1,Object o2) {
// 将Object类型参数强转为String类型
String s1 = (String) o1;
String s2 = (String) o2;
return s2.compareTo(s1); // 返回比较之后的值
}
}
程序的运行结果如下:
Girl4:杨玉环 Girl3:西施 Girl2:王昭君 Girl1:貂蝉程序中是按照键为 Girl3、Girl2、Girl1、Girl4 的顺序,将元素存入集合的,运行结果中显示元素是按降序排列的,这是因为本例自定义的 TestComparator 类实现的 compare(Object o1, Object o2)方法重写了排序逻辑,这就是 TreeMap 集合的定制排序。
Java Properties集合
Hashtable 是 Map 接口中一个早期的并且线程安全的实现类。与 HashMap 类似的是,Hashtable 存储的键值对数据也是无序的,它判断键是否相等的方式与 HashMap 类是相同的。但是,与 HashMap 不同的是,它的键和值都不允许使用 null。Hashtable 类因为要确保线程安全,所以存取元素速度比较慢,目前用的比较少。不过它的子类 Properties 在实际开发中用的比较多,该子类对象主要用于处理 properties 属性文件,由于属性文件里的键和值都是字符串类型,所以 Properties 集合里的键和值都是字符串类型。
这里给出 Properties 类的常用方法,如下表所示:
| 方法 | 方法描述 |
|---|---|
| String getProperty(String key) | 根据键获取值 |
| String getProperty(String key, String defaultValue) | 根据 key 获取对应的值。如果值不存在,则直接将 defaultValue 作为返回值 |
| Object setProperty(String key, String value) | 以键值对的方式设置数据。如果键存在,则覆盖之前的数据;如果键不存在,则添加数据 |
| void load(InputStream inStream) | 通过输入流从属性文件中加载键值对数据,加载到的键值对数据添加到 Properties 里 |
| void store(OutputStream out, String s) | 通过输出流将 Properties 中的键值对输出到指定文件 |
接下来,通过案例来演示 Properties 类的用法:
import java.io.FileOutputStream;
import java.util.Properties;
public class Demo {
public static void main(String[] args) throws Exception {
// 创建Properties集合类对象
Properties pro = new Properties();
// 向Properties集合中添加键值对数据
pro.setProperty("username", "AAA");
pro.setProperty("password", "123456");
// 将Properties集合中的属性保存到当前项目根目录下程序自动创建的data.ini文件中
pro.store(new FileOutputStream("data.ini"), "title");
}
}
上面程序运行后,会在项目根目录下生成一个名为 data.ini 的文件,文件内容如下:
#title
#Wed Jan 13 19:19:44 CST 2021
password=123456
username=AAA
ICP备案:
公安联网备案: