前言
集合 —— 操作批量数据的核心工具
在 Dart 中,Map 是一种非常强大的数据结构,它允许存储键值对(key-value pairs),其中每个键都是唯一的。Map 类似于现实世界中的字典或电话簿——通过一个唯一的标识符(键)来查找对应的信息(值)。本章节将深入理解 Dart 中的 Map,系统化掌握其创建、操作和优化方法。
操千曲而后晓声,观千剑而后识器。虐它千百遍方能通晓其真意。
一、基本概念
1.1、图像表示
| 姓名 | 电话 |
|---|---|
| Alice | 19999999999 |
| Bob | 18888888888 |
| Charlie | 17777777777 |
如上图所示,有一个班级的学生电话簿,左边是人名,右边是对应的电话号码。想找某个人的电话时,只需要知道名字就可以快速找到电话号码。这就是 Map 的工作方式 —— 它由键(Key)和值(Value)组成,通过键来查找对应的值。
1.2、定义
Map 是一个无序的键值对集合,其中每个键是唯一的。可以通过键快速查找对应的值,非常适合用于关联数据的场景,如配置文件解析、用户信息管理等。
Map<String, String> infos = {'Alice':"19999999999", 'Bob': "18888888888", 'Charlie': "17777777777"};
1.3、特点
- 1、键唯一性:每个键只能出现
一次。 - 2、值可以重复:不同
键可以对应相同的值。 - 3、无序性:
Map中的元素没有固定的顺序。
// 学生电话薄
Map<String, String> infos = {'Alice':"19999999999", 'Bob': "18888888888", 'Charlie': "17777777777"};
// 查找某个学生的电话
print(infos["Alice"]); // 输出: 19999999999
// 添加新的学生信息
infos["David"] = '16666666666';
// 输出学生信息
print(infos); // 输出: {Alice: 19999999999, Bob: 18888888888, Charlie: 17777777777, David: 16666666666}
1.4、泛型支持
Dart 的 Map 支持泛型,允许指定映射中元素的具体类型,从而提高代码的类型安全性和可读性。
二、创建和初始化
2.1、直接创建
最简单的方式是直接在花括号{}中列出键值对。
Map<String, int> ages = {'Alice': 30, 'Bob': 25, 'Charlie': 35};
2.2、使用构造函数
使用 Map 类的构造函数来创建一个空Map或具有初始键值对的Map。
// 创建一个空 Map
Map<String, int> emptyMap = <String, int>{};
// 创建一个包含初始键值对的 Map
Map<int, String> numbersToWords = Map<int, String>.from({
1: 'one',
2: 'two',
3: 'three'
});
2.3、 使用Map.of 构造函数
Map.of 可以从另一个 Map 创建一个新的 Map,确保键值对的独立性。
Map<String, String> original = {'apple': '苹果', 'banana': '香蕉'};
Map<String, String> copy = Map.of(original);
2.4、 使用Map.fromIterable 和 Map.fromEntries
Map.fromIterable:根据可迭代对象创建Map,并指定键和值生成器。Map.fromEntries:根据可迭代的MapEntry对象创建Map。Map.of可以从另一个Map创建一个新的Map,确保键值对的独立性。
List<String> keys = ['apple', 'banana'];
List<String> values = ['苹果', '香蕉'];
Map<String, String> fruits = Map.fromIterables(keys, values);
List<MapEntry<String, String>> entries = [
MapEntry('apple', '苹果'),
MapEntry('banana', '香蕉')
];
Map<String, String> fruitsFromEntries = Map.fromEntries(entries);
三、访问和修改
3.1、访问元素
使用键来访问对应的值。
Map<String, int> ages = {'Alice': 30, 'Bob': 25, 'Charlie': 35};
print(ages['Alice']); // 输出: 30
3.2、修改元素
可以通过键直接修改对应的值。
ages['Alice'] = 31;
print(ages['Alice']); // 输出: 31
3.3、添加元素
如果键不存在,则添加新的键值对;如果键存在,则更新对应的值。
ages['David'] = 28;
print(ages); // 输出: {Alice: 31, Bob: 25, Charlie: 35, David: 28}
3.4、移除元素
- 1、移除键值对:使用
remove方法。
ages.remove('Bob');
print(ages); // 输出: {Alice: 31, Charlie: 35, David: 28}
- 2、清空
Map:使用clear方法。
ages.clear();
print(ages); // 输出: {}
四、遍历
4.1、使用forEach
forEach 方法允许为 Map 中的每个键值对执行一个回调函数。
ages.forEach((key, value) => print('$key: $value'));
4.2、使用 entries 属性结合for-in循环
for (var entry in ages.entries) {
print('${entry.key}: ${entry.value}');
}
五、常用属性和方法
5.1、属性
// length:获取 Map 的大小(键值对的数量)
print(ages.length);
// isEmpty 和 isNotEmpty:检查 Set 是否为空。
print(emptySet.isEmpty);
5.2、常用方法
- 1、查找键或值:
// 1、使用 containsKey 检查某个键是否存在。 print(ages.containsKey('Alice')); // 输出: true // 2、使用 containsValue 检查某个值是否存在。 print(ages.containsValue(30)); // 输出: true - 2、获取所有的键或值:
// 1、使用 `keys` 属性获取所有键。 print(ages.keys); // 输出: (Alice, Bob, Charlie) // 2、使用 values 属性获取所有值。 print(ages.values); // 输出: (30, 25, 35) - 3、合并
Map:// 使用 addAll 方法将另一个 Map 的键值对添加到当前 Map Map<String, int> moreAges = {'Eve': 32}; ages.addAll(moreAges); print(ages); // 输出: {Alice: 30, Bob: 25, Charlie: 35, Eve: 32}
六、不可变Map(Map.unmodifiable)
有时需要确保一个 Map 不会被修改。可以使用 Map.unmodifiable 来创建一个不可变的 Map。
Map<String, int> immutableAges = Map.unmodifiable({'Alice': 30, 'Bob': 25});
// 下面这行代码会抛出异常,因为 immutableAges 是不可变的
// immutableAges['Charlie'] = 35;
七、总结
Map 提供了一种强大而灵活的方式来处理键值对数据。通过合理利用 Map 的特性,可以编写出更加简洁、高效和易于维护的代码。
欢迎一键四连(
关注+点赞+收藏+评论)