Map集合类_演练
见书P261
参考:《Java核心技术卷1》
引入
将“关键字”简称为“键”。通过Map
接口可以实现存储“键/值”的映射关系(简称“键值对”)。
在许多教材中Map
被翻译为映射。
什么是键?什么是值?
手机上的联系人,就是一个最典型的映射(map)。
想象一下,你的手机里保存了很多联系人的信息。每个联系人都有一个名字,而每个名字对应着一个电话号码。
在这里,名字就是所谓的“键”,电话号码就是“值”。
举个例子:张三的电话号码是123-456-7890
,那么这里张三就是键,123-456-7890
就是值。
键必须是唯一的。也就是说,不能有两个张三。
如果提供了键,就可以查找一个值。即,通过名字可以查找电话号码。
映射
主要方法
Map
接口中定义了哪些主要的抽象方法?如下图。
HashMap类
Map
中定义的仅仅是抽象方法,要想真正使用Map
必须依赖于具体的实现类。
Map
接口有许多实现类,HashMap
是最常用的一个,它可被称为散列映射或者哈希表。
例如,可以用下面的方法建立一个哈希表来存储联系人信息:
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class MyTest {
public static void main(String[] args) {
// 1 创建 HashMap 类对象
Map<String, String> map = new HashMap<>();
// Map接口是泛型接口, HashMap类是泛型类
// 需要在尖括号中指定 键 和 值 类型
// 2 用 put 方法向映射中添加键值对
map.put("zhangsan", "123-456-7890");
map.put("lisi", "234-567-8901");
map.put("wangwu", "345-678-9012");
// 3 根据键获取值
String tmp = map.get("zhangsan");
System.out.println(tmp);
// 4 模拟查找默认电话
String name = new Scanner(System.in).next();
if (map.containsKey(name)) {
System.out.println(name + "的电话: " + map.get(name));
} else {
System.out.println(name + "不在联系人列表中");
}
// 5 删除指定键的映射
map.remove("zhangsan");
// 6 输出整个联系人列表
System.out.println("*******************************");
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("姓名: " + key + ", 电话: " + value);
}
}
}
上面代码中的Map.Entry
是什么?写法上像静态变量,但通过查看源代码可发现Map.Entry
其实是定义在Map
中的一个嵌套接口。它代表 Map
中的一个键值对(需注意,它也是一个泛型接口)。它实际上就是 Map
中每个元素的一个抽象,包含了1个键和1个值。可通过 entry.getKey()
获取键,entry.getValue()
获取值。补充代码:
public class MyTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("zhangsan", "123");
map.put("lisi", "321");
Set<Map.Entry<String, String>> set = map.entrySet();
// entrySet会返回一个Set类型的对象 ,这个Set是一个泛型接口
// 因此需要在尖括号中指定Set中保存的元素类型
// 它保存的元素类型叫 Map.Entry, 每个Map.Entry表示一个键值对
// 而 Map.Entry 也是一个泛型类,需要在尖括号中指定键和值的类型
// 所以就需要两个尖括号
// 一个set里面有 n个 Map.Entry, 每个Map.Entry = 1个键 + 1个值
for (Map.Entry<String, String> entry : set) {
String name = entry.getKey();
String number = entry.getValue();
System.out.println(name + ": " + number);
}
}
}
键必须是唯一的
不能对同一个键存放两个值。如果用同一个键调用两次put
方法,第二个值就会取代第一个值。实际上,put
将返回与这个键参数关联的上一个值。
import java.util.HashMap;
import java.util.Map;
public class MyTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("zhangsan", "123");
System.out.println("zhangsan的号码: " + map.get("zhangsan"));
String previous = map.put("zhangsan", "新号码"); // 新号码将123取代了!
System.out.println("zhangsan的号码: " + map.get("zhangsan"));
System.out.println("zhangsan的旧号码: " + previous);
}
}
参考输出:
zhangsan的号码: 123
zhangsan的号码: 新号码
zhangsan的旧号码: 123
假设通过put
存放一个新的键put
将返回什么呢?
无序存储
例如,以下代码
import java.util.HashMap;
import java.util.Map;
public class MyTest {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("zhangsan", "123-456-7890");
map.put("lisi", "234-567-8901");
map.put("wangwu", "345-678-9012");
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("姓名: " + key + ", 电话: " + value);
}
}
}
的输出是:
姓名: lisi, 电话: 234-567-8901
姓名: zhangsan, 电话: 123-456-7890
姓名: wangwu, 电话: 345-678-9012
显然是不按照插入顺序的。因此,只有不关心集合中元素的顺序时才应该使用HashMap
。
练习
热身练习
如听讲过程未完成上述代码(第一段:存储联系人信息)的继续完成。
练习(★★★★★)
创建2个字符串数组,第一个数组内容为:[黑龙江省,浙江省,江西省,广东省,福建省]
,
第二个数组为:[哈尔滨,杭州,南昌,广州,福州]
,
将第一个数组元素作为key
,第二个数组元素作为value
存储到Map
集合中。
删除Map
集合中Key=黑龙江省的键值对。
迭代Map
集合,参考的输出数据格式如下:
福建省=福州
浙江省=杭州
江西省=南昌
广东省=广州
可通过.length
获取数组长度(考试不会提供该参考代码!):
// 第一个数组
String[] provinces = {"黑龙江省", "浙江省", "江西省", "广东省", "福建省"};
// 第二个数组
String[] cities = {"哈尔滨", "杭州", "南昌", "广州", "福州"};
System.out.println(provinces.length); // => 5