话接上回,继续Java集合框架的学习,这次主要介绍Map接口。

一、Map概述

1、Map

Map是一种键-值对(key-value)集合, 集合中的每一个元素都包含一个键(key)对象和一个值(value)对象。用于保存具有映射关系的数据(Map是一种映射表,可以通过key快速查找value)。

2、Map接口

存放一对值的最大接口(接口中的每个元素都是一对,以 key-value 的形式保存)。

3、几点注意

Map 集合里保存着两组值,一组值用于保存 Map 里的 key,另外一组值用于保存 Map 里的 value,key 和 value 都可以是任何引用类型的数据。key 不允许重复,value 可以重复(同一个 Map 对象的任何两个 key 通过 equals 方法比较总是返回 false)

Map 中的 key 和 value 之间存在单向一对一关系,即通过指定的 key,总能找到唯一的、确定的 value。

Map 接口主要有两个实现类:HashMap 类和 TreeMap 类。其中,HashMap 类按哈希算法来存取键对象,而 TreeMap 类可以对键对象进行排序。

4、常用方法

不用死记,不记得时鼠标定位或选中HashMap/TreeMap,按ctrl+B查看源码及对应的方法。

containsKey(Object key)、containsValue(Object value):是否包含指定key,一个或多个value(键唯一,值可重复)

get(Object key):获取指定键对应的值

put(K key, V value)、putAll(Map m):添加键值对(已有则覆盖)/复制指定 Map 中的键值对到本 Map 中

remove(Object key)、 remove(Object key, Object value):移除指定key对应的元素/指定key对应的键值。

Set entrySet()、Set keySet():返回Map集合中所有键值对的 Set 集合/返回 Map 集合中所有键对象的 Set 集合

clear()、isEmpty()、size()、Collection values():返回Map中所有 value 组成的 Collection

5、案例

需求:使用 HashMap 来存储学生信息,其键为学生学号,值为姓名。毕业时,需要用户输入学生的学号,并根据学号进行删除操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.util.HashMap; //导包
import java.util.Iterator;
import java.util.Scanner;

public class MapDemo {
public static void main(String[] args){
HashMap users=new HashMap(); //创建HashMap集合对象
users.put("11", "张三"); // 向Map集合中添加键值对
users.put("22", "李四");
users.put("33", "王五");
users.put("44", "赵六");
users.put("55", "王八");
System.out.println("***** 学生列表 *****");
Iterator it=users.keySet().iterator(); //获取迭代器,keySet()返回Map集合中所有键对象的Set集合
//由于迭代器是Collection中的方法,所以先利用keySet()把Map转化为Set集合(Collection的子接口),才能获取迭代器
while (it.hasNext()){ //遍历集合
//两种类型(1统一Object类,不用强转.2强转:String key=(String) it.next();
Object key= it.next(); //获取并迭代键
Object val=users.get(key); //获取键对应的值
System.out.println("学号:"+key+" "+"姓名:"+val);
}
Scanner sc=new Scanner(System.in);
System.out.println("请输入要删除的学号:");
int sno= sc.nextInt();
// 判断是否包含指定键
if(users.containsKey(String.valueOf(sno))){ //String.valueOf(),将其他类型对象转化为字符串类型
users.remove(String.valueOf(sno));
}else {
System.out.println("该学生不存在!");
}
System.out.println("***** 学生列表 *****");
it=users.keySet().iterator(); //获取迭代器,keySet()返回Map集合中所有键对象的Set集合
while(it.hasNext()){ //遍历
Object key=it.next(); //获取并迭代键
Object val=users.get(key); //获取键对应的值
System.out.println("学号:"+key+" "+"姓名:"+val);
}
}
}

运行结果

1
2
3
4
5
6
7
8
9
10
11
12
13
***** 学生列表 *****
学号:11 姓名:张三
学号:22 姓名:李四
学号:33 姓名:王五
学号:44 姓名:赵六
学号:55 姓名:王八
请输入要删除的学号:
22
***** 学生列表 *****
学号:11 姓名:张三
学号:33 姓名:王五
学号:44 姓名:赵六
学号:55 姓名:王八

注:TreeMap 类的使用方法与 HashMap 类相同,唯一不同的是 TreeMap 类可以对键对象进行排序。

6、Map集合的遍历(4种方法)

6.1 方法说明

List 和 Set 集合的遍历不同,Map有两组值(可以只遍历值,或只遍历键,或同时遍历),Map 及实现 Map 的接口类(如 HashMap、TreeMap、LinkedHashMap、Hashtable 等)都能用以下几种方式遍历。

entries方法(最常见也最常用)

for-each循环(一般只遍历键或只遍历值时使用,性能较entrySet好)

Iterator迭代器

键取值(get方法)遍历(效率低,耗时)

6.2 示例

1) entries方法

1
2
3
4
5
6
7
8
9
10
11
12
public class HashMapDemo1 {
public static void main(String[] args){
Map<String,String> map=new HashMap<>(); // 创建HashMap集合对象,使用泛型指定键值的类型
map.put("我的个人小站", "https://zhengyquan.gitee.io/"); // 添加键值对
map.put("我的腾讯云社区首页", "https://cloud.tencent.com/developer/user/10491946");
for(Map.Entry<String,String> entry: map.entrySet()){ // entries方法遍历
String mapKey=entry.getKey(); //获取键
String mapValue= entry.getValue(); //获取值
System.out.println(mapKey+":"+mapValue); //输出结果
}
}
}

运行结果

1
2
我的腾讯云社区首页:https://cloud.tencent.com/developer/user/10491946
我的个人小站:https://zhengyquan.gitee.io/

2)for-each循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.HashMap; //导包
import java.util.Map;

public class HashMapDemo1 {
public static void main(String[] args){
Map<String,String> map=new HashMap<>(); // 创建HashMap集合对象,使用泛型指定键值的类型
map.put("我的个人小站", "https://zhengyquan.gitee.io/"); // 添加键值对
map.put("我的腾讯云社区首页", "https://cloud.tencent.com/developer/user/10491946");
for(String key:map.keySet()){ // 使用for-each遍历键集合
System.out.println(key);
}
for(String value: map.values()){ // 使用for-each遍历值集合
System.out.println(value);
}
}
}

运行结果

1
2
3
4
我的腾讯云社区首页
我的个人小站
https://cloud.tencent.com/developer/user/10491946
https://zhengyquan.gitee.io/

3)Iterator迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.HashMap; //导包
import java.util.Iterator;
import java.util.Map;

public class HashMapDemo1 {
public static void main(String[] args){
Map<String,String> map=new HashMap<>(); // 创建HashMap集合对象,使用泛型指定键值的类型
map.put("我的个人小站", "https://zhengyquan.gitee.io/"); // 添加键值对
map.put("我的腾讯云社区首页", "https://cloud.tencent.com/developer/user/10491946");
Iterator<Map.Entry<String,String>> entries=map.entrySet().iterator(); //获取迭代器对象
while(entries.hasNext()){ //hasNest()迭代遍历
Map.Entry<String,String> entry=entries.next();
String key=entry.getKey(); //获取键
String value=entry.getValue(); //获取值
System.out.println(key+":"+value);
}
}
}

运行结果

1
2
我的腾讯云社区首页:https://cloud.tencent.com/developer/user/10491946
我的个人小站:https://zhengyquan.gitee.io/

4)键取值(get()方法)遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.util.HashMap; //导包
import java.util.Map;

public class HashMapDemo1 {
public static void main(String[] args){
Map<String,String> map=new HashMap<>(); // 创建HashMap集合对象,使用泛型指定键值的类型
map.put("我的个人小站", "https://zhengyquan.gitee.io/"); // 添加键值对
map.put("我的腾讯云社区首页", "https://cloud.tencent.com/developer/user/10491946");
for(String key : map.keySet()){ //for-each循环
String value = map.get(key); //get()方法获取值,键取值
System.out.println(key+":"+value);
}
}
}

运行结果

1
2
我的腾讯云社区首页:https://cloud.tencent.com/developer/user/10491946
我的个人小站:https://zhengyquan.gitee.io/

二、HashMap

1、概述

HashMap 是最常用的一种Map实现,按哈希算法来存取键对象(即根据键的 HashCode 值存储数据),具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap是一种以空间换时间的映射表,它的实现原理决定了内部的Key是无序的,即遍历HashMap的Key时,其顺序是不可预测的(但每个Key都会遍历一次且仅遍历一次)。
HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。

2、常用方法

列举几个,其他方法ctrl+B查看源码或网站/API帮助文档

  • 添加元素:put()、putAll()..
  • 访问元素:get(key)..
  • 删除元素:remove(key)
  • 清除所有:clear()、计算大小:size()、迭代:for-each…

3、示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.HashMap;

public class HashMapDemo {
public static void main(String[] args){
//创建HashMap集合对象,使用泛型指定键值的类型,使用基本类型的包装类
HashMap<Integer,String> name=new HashMap<>();
name.put(1,"zhangsan"); //向集合name中添加键值对
name.put(2,"lishi");
name.put(3,"wangwu");
name.put(4,"zhaoliu");
System.out.println("name集合:"+name);

HashMap<Integer,String> name1=new HashMap<>();
name1.put(5,"xiaoming"); //向集合name1中添加键值对
name1.put(6,"wangba");
name.putAll(name1); //将name1所有键/值对添加到name集合中
System.out.println("添加name1集合中所有键值对后的name集合:"+name);
System.out.println("name集合的大小:"+name.size()); //大小
System.out.println("获取name集合中键为4对应的值:"+name.get(4)); //获取值
name.remove(4); //移除键值对
System.out.println("删除name集合中键为4对应键值对后的name集合:"+name);
name.clear(); //清空集合
System.out.println("清空name集合:"+name);
}
}

运行结果

1
2
3
4
5
6
name集合:{1=zhangsan, 2=lishi, 3=wangwu, 4=zhaoliu}
添加name1集合中所有键值对后的name集合:{1=zhangsan, 2=lishi, 3=wangwu, 4=zhaoliu, 5=xiaoming, 6=wangba}
name集合的大小:6
获取name集合中键为4对应的值:zhaoliu
删除name集合中键为4对应键值对后的name集合:{1=zhangsan, 2=lishi, 3=wangwu, 5=xiaoming, 6=wangba}
清空name集合:{}

三、TreeMap(了解)

1、概述

  • 可以对键对象进行排序(HashMap不能,其他使用方法与 HashMap 类相同)

    • 是SortedMap(接口)的实现类,在内部会对Key进行排序。
  • 使用TreeMap时,放入的Key必须实现Comparable接口,如果没有实现,必须在创建TreeMap时同时指定一个自定义排序算法

    • String、Integer这些类已经实现了Comparable接口,因此可以直接作为Key使用。作为Value的对象则没有任何要求。