前言
你是否需要将数据以键值对的形式关联,例如快速查询商品信息,或是实现高效的数据索引?在Dart中,Map正是为此而设计的核心数据结构。与List和Set不同,Map通过唯一的键(Key)关联值(Value),既能像字典一样直观检索,又能以接近O(1)的时间复杂度实现快速查找,成为处理复杂数据关系的“神器”。现在就让我们一起来了解一下这把处理复杂数据关系的“神器”怎么使用吧。
一、基本概念
1.1、定义
映射(Map)是无序的键值对集合。包含键和值两个部分,其中键具有唯一性,即不同键可以对应相同的值。
如图所示,每一个键(唯一)都对应一个值(可以重复)。
1.2、特点
- 无序:映射中的元素没有按照一定的顺序进行排列。
- 键具有唯一性。
- 值可以重复。
1.3、泛型支持
Dart中映射(Map)和列表(List)集合(Set)一样,不仅支持指定元素为同一类型,也支持元素为不同类型(通过动态类型声明dynamic)。
二、创建和初始化
2.1、直接创建
映射(Map)和集合(Set)一样可通过大括号({})直接创建。
示例:
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'James':54,'Daniel':8,'Sophia':12,'Emma':2};
}
2.2、使用构造函数创建
- <String,int>{}:创建一个空映射。
- Map<String,int>.from() 创建。
示例:
void main() {
Map<String,int> emptyMap = <String,int>{};
print(emptyMap); // 输出:{}
Map<String,int> fromMap = Map<String,int>.from({'John':2,'Michael':23,'David':23});
print(fromMap); // 输出:{John: 2, Michael: 23, David: 23}
}
2.3、使用Map.of创建
映射(Map)和集合(Set)类似都可通过 of() 构造函数进行创建。
示例:
void main() {
Map<String,int> ofMap = Map.of({'John':2,'Michael':23,'David':23});
print(ofMap); // 输出:{John: 2, Michael: 23, David: 23}
}
2.4、使用Map.fromIterables和Map.fromEntries创建
- Map.fromIterables():第一个参数为键的可迭代对象,第二个为值的可迭代对象。
- Map.fromEntries():参数为以MapEntry对象为元素的可迭代对象。
示例:
void main() {
List<String> keyList = ['John','Michael','David'];
List<int> valueList = [2,23,23];
Map<String,int> fromIterablesMap = Map.fromIterables(keyList,valueList);
print(fromIterablesMap); // 输出:{John: 2, Michael: 23, David: 23}
// 创建MapEntry对象的列表entries。
List<MapEntry<String,int>> entries = [MapEntry('John', 2),MapEntry('Michael', 23),MapEntry('David', 23)];
Map<String,int> fromEntriesMap = Map.fromEntries(entries);
print(fromEntriesMap); // 输出:{John: 2, Michael: 23, David: 23}
}
三、不可变映射
Dart映射(Map)与集合(Set)、列表(List)相同,都支持定义不可修改的对象。映射(Map)使用Map.unmodifiable()构造函数创建。
示例:
void main() {
Map<String,int> unmodifiableMap = Map.unmodifiable({'John':2,'Michael':23,'David':23});
print(unmodifiableMap); // 输出:{John: 2, Michael: 23, David: 23}
// 尝试修改内容
unmodifiableMap.addAll({'Daniel':8,'Sophia':12,'Emma':2});
// Unsupported operation: Cannot modify unmodifiable map
}
运行时报错:
四、常用属性和方法
4.1、常用属性
- length:获取映射的键值对个数。
- isEmpty:判断映射中是否为空映射。为空则返回true,否则返回false。
- keys:获取映射中的所有键。
- values:获取映射中的所有值。
- entries:获取映射中的所有MapEntry对象。
示例:
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'James':54,'Daniel':8,'Emma':2};
print(scoresMap.length); // 输出:6
print(scoresMap.isEmpty); // 输出:false
print(scoresMap.keys); // 输出:(John, Michael, David, James, Daniel, Emma)
print(scoresMap.values); // 输出:(2, 23, 23, 54, 8, 2)
print(scoresMap.entries);
// 输出:(MapEntry(John: 2), MapEntry(Michael: 23), MapEntry(David: 23), ..., MapEntry(Daniel: 8), MapEntry(Emma: 2))
}
4.2、常用方法
- containsKey():判断映射键中是否包含某个键。
- containsValue():判断映射值中是否包含某个值
示例:
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'James':54,'Daniel':8,'Emma':2};
print(scoresMap.containsKey('John')); // 包含键John 输出:true
print(scoresMap.containsValue(1200)); // 不包含值1200 输出:false
}
五、访问元素
映射(Map)除了不仅支持遍历,还支持通过键访问键值对的值。
5.1、通过键访问
映射中每个键与每个值一一对应。因此可以通过键来访问值(就像列表中使用下标访问元素)。
示例:
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'James':54,'Daniel':8,'Emma':2};
print(scoresMap['John']); // 输出:2
}
5.2、遍历
将映射中的元素访问一遍。
- for-in遍历,结合
entries属性。 - 高阶函数 forEach() 遍历。
示例: for-in遍历
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'James':54,'Daniel':8,'Emma':2};
for (var entry in scoresMap.entries){
print('${entry.key} : ${entry.value}');
}
}
示例: 高阶函数forEach()遍历
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'James':54,'Daniel':8,'Emma':2};
scoresMap.forEach((key,value) => print('$key : $value'));
}
六、添加元素
- 可通过键添加键值对。如果添加的键在映射中存在,则将映射中键对应的值进行更新。
- addAll():批量添加键值对。
- addEntries():通过MapEntry对象添加键值对。
示例: 通过键添加
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'Emma':2};
scoresMap['Emma'] = 1200;
print(scoresMap); // 更新scoresMap中Emma的值 输出:{John: 2, Michael: 23, David: 23, Emma: 1200}
scoresMap['Daniel'] = 234;
print(scoresMap); // 输出:{John: 2, Michael: 23, David: 23, Emma: 1200, Daniel: 234}
}
示例: addAll()与addEntries()添加
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'Emma':2};
scoresMap.addAll({'Daniel': 234});
print(scoresMap); // 输出:{John: 2, Michael: 23, David: 23, Emma: 1200, Daniel: 234}
scoresMap.addEntries([MapEntry('Michael',23),MapEntry('Sophia',12)]);
print(scoresMap); // 输出:{John: 2, Michael: 23, David: 23, Emma: 2, Daniel: 234, Sophia: 12}
}
七、修改元素
通过键访问到元素,再进行修改。
示例:
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'Emma':2};
scoresMap['John'] = 1200;
print(scoresMap); // 输出:{John: 1200, Michael: 23, David: 23, Emma: 2}
}
八、移除元素
- remove():移除某个键值对。
- removeWhere():移除满足一定条件的键值对。
- clear():清空映射中键值对。
示例:
void main() {
Map<String,int> scoresMap = {'John':2,'Michael':23,'David':23,'Emma':2};
scoresMap.remove('John');
print(scoresMap); // 输出:{Michael: 23, David: 23, Emma: 2}
// 移除Michael键值对。
scoresMap.removeWhere((key,value) => key=='Michael');
print(scoresMap); // 输出:{David: 23, Emma: 2}
scoresMap.clear();
print(scoresMap); // 输出:{}
}
九、总结
本小节归纳总结如下:
| 属性或方法 | |
|---|---|
| 创建和初始化 | 1、使用{}直接创建2、 Map<String,int>.from()3、 Map<String,int>.fromIterables()4、 Map<Sring,int>.fromEntries()5、 Map.of() |
| 不可变映射 | 使用Map.unmodifiable()创建 |
| 常用属性和方法 | 1、length属性 2、isEmpty属性 3、keys属性4、 values属性 5、Entries属性1、 containsKey()方法 2、containsValue()方法 |
| 访问元素 | 1、使用键访问 2、 for-in循环遍历(结合Entries属性)3、高阶函数 forEach()遍历 |
| 添加元素 | 1、使用键添加 2、 addAll() 3、 addEntries() |
| 修改元素 | 先访问,再修改 |
| 移除元素 | 1、remove()移除键值对2、 removeWhere()移除符合条件的键值对 3、 clear()清空映射中所有键值对 |