系统化掌握Dart编程之映射 (Map)(一):筑基之旅

668 阅读5分钟

image.png

前言

集合 —— 操作批量数据核心工具

Dart 中,Map 是一种非常强大的数据结构,它允许存储键值对key-value pairs),其中每个键都是唯一的Map 类似于现实世界中的字典电话簿——通过一个唯一的标识符)来查找对应的信息)。本章节将深入理解 Dart 中的 Map,系统化掌握其创建操作优化方法。

千曲而后晓声,观千剑而后识器。虐它千百遍方能通晓其真意

一、基本概念

1.1、图像表示

姓名电话
Alice19999999999
Bob18888888888
Charlie17777777777

如上图所示,有一个班级的学生电话簿,左边是人名,右边是对应的电话号码。想找某个人的电话时,只需要知道名字就可以快速找到电话号码。这就是 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、泛型支持

DartMap 支持泛型,允许指定映射中元素的具体类型,从而提高代码的类型安全性可读性

二、创建和初始化

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.fromIterableMap.fromEntries

  • Map.fromIterable:根据可迭代对象创建 Map,并指定键和值生成器。
  • Map.fromEntries:根据可迭代的 MapEntry 对象创建 MapMap.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 的特性,可以编写出更加简洁高效和易于维护的代码。

欢迎一键四连关注 + 点赞 + 收藏 + 评论