# Dart教程 - 6 容器
什么是容器?
容器就是可以存储多个数据的一种数据类型,容器内的每一个数据称之为元素,其中的元素可以是任意类型的数据,包括字符串、数字、布尔,甚至是容器等等。
例如有一个班级,有40个学生,我们肯定不能定义40个变量来存储学生的信息,有1000个人,那不要命了,我们可以将所有学生的信息放到容器中。
在Dart中常用的容器分为3类:
- 列表(list)
- 集合(set)
- 字典(map)
不同的容器有不同的特点,例如:
- 是否支持重复的元素,有的容器中的元素不能重复,有的可以。
- 是否有序
下面一一介绍。
# 6.1 List
List 列表就是一个普通的容器,满足你最原始的想象,主要有如下特点:
- 列表中的元素可以重复
- 列表中的元素可以修改,可以增加、修改、删除
- 列表中的元素是有序的,可以通过索引来访问
- 列表中可以存储不同数据类型的数据
# 1 创建List
// 方式一:创建一个空列表
List<String> emptyList = [];
// 方式二:创建一个包含元素的列表
List<int> numbers = [1, 2, 3, 4, 5];
2
3
4
5
当然使用 var
来声明也是可以的。
var emptyList = [];
var emptyList = [1, 2, 3, 4, 5];
2
还可以通过来创建定长的List,定长的List长度是固定的,所以不能添加和删除元素,但是可以修改元素。
// 创建定长的列表
List<int> list = List.filled(5, 2); // 创建一个定长的List
print(list); //[2, 2, 2, 2, 2]
2
3
第一个参数5表示List的长度,第二个2表示所有的元素都是2。
# 2 基础操作
# 添加元素
var numbers = [];
numbers.add(1);
numbers.add(2);
numbers.add(3);
2
3
4
# 访问元素
可以使用下标来访问列表中的元素,从0开始,注意不要越界。
var numbers = [1, 2, 3];
print(numbers[0]); // 1
2
# 获取长度
var numbers = [1, 2, 3];
print(numbers.length); // 3
2
# 插入元素
var numbers = [1, 2, 3];
numbers.insert(1, 4);
print(numbers); // [1, 4, 2, 3]
2
3
也可以在执行位置插入数组:
numbers.insertAll(1, [4, 5]); //[1, 4, 5, 2, 3]
# 删除元素
var numbers = [1, 2, 3];
numbers.remove(2);
print(numbers); // [1, 3]
2
3
也可以使用removeAt(index)函数删除指定index的元素。
# 清空List
var numbers = [1, 2, 3];
numbers.clear();
print(numbers); // []
2
3
# 3 遍历List
当遍历 Dart 中的列表时,您可以使用以下方法:
使用 for
循环
List<String> fruits = ['apple', 'banana', 'orange'];
for (int i = 0; i < fruits.length; i++) {
print(fruits[i]);
}
2
3
4
5
在 for
循环中,使用列表的长度 fruits.length
作为循环条件,以便在每个索引位置上访问列表元素 fruits[i]
。
使用 for-in
循环
List<String> fruits = ['apple', 'banana', 'orange'];
for (var fruit in fruits) {
print(fruit);
}
2
3
4
5
在 for-in
循环中,将每个列表元素 fruit
赋值给变量 var fruit
,然后在循环体中执行相应的操作。这种方法比使用 for
循环更简洁,特别是当您不需要访问每个元素的索引时。
使用 forEach
方法
List<String> fruits = ['apple', 'banana', 'orange'];
fruits.forEach((fruit) {
print(fruit);
});
2
3
4
5
在 forEach
方法中,您需要提供一个回调函数 (fruit) => { print(fruit) }
,该回调函数将在列表的每个元素上执行相应的操作。这种方法的优点是语法简洁,易于阅读。
使用迭代器
List<String> fruits = ['apple', 'banana', 'orange'];
Iterator<String> iterator = fruits.iterator;
while (iterator.moveNext()) {
print(iterator.current);
}
2
3
4
5
6
7
在使用迭代器遍历列表时,首先需要获取列表的迭代器 fruits.iterator
,然后可以使用 while
循环和迭代器的 moveNext()
和 current
方法来访问列表的每个元素。
# 4 其他常用操作
# 判断List是否为空
可以通过isEmpty()方法判断List是否为空,通过isNotEmpty()方法判断List是否不为空。
var numbers = [];
if (numbers.isEmpty) {
print("集合为空");
}
numbers = [1, 2, 3, 4, 5];
if (numbers.isNotEmpty) {
print("集合不为空");
}
2
3
4
5
6
7
8
9
# 检查包含某个元素
var numbers = [1, 2, 3];
print(numbers.contains(2)); // true
2
# 将List中的元素拼接成字符串
使用joint()方法,可以将List中的元素,使用指定的连接符,拼接成一个字符串。
举个栗子:
var numbers = [1, 2, 3];
var numberString = numbers.join(', ');
print(numberString); //输出:1, 2, 3
2
3
# 将字符串分割成List
我们可以将一个字符串,使用指定的分隔符,将字符串分割成一个List。
举个栗子:
String str = "1,2,3,4,5";
List<String> list = str.split(",");
print(list); //输出:[1, 2, 3, 4, 5]
2
3
# 使用List中的元素生成新的List
使用map方法,可以依次取出List中的元素,然后进行处理,得到一个新的List。
举个栗子:
将一个List中的元素乘以2得到一个新的List。
var numbers = [1, 2, 3];
var doubledNumbers = numbers.map((number) {
return number * 2;
}).toList();
print(doubledNumbers); // [2, 4, 6]
2
3
4
5
6
7
map得到的结果使用toList()方法转换为List。
也可以使用lambda表达式来简写:var doubledNumbers = numbers.map((number) => number * 2).toList();
# 过滤List中的元素
使用 where
方法,可以使用指定的条件过滤List中的元素,组成一个新的List。
举个栗子:
var numbers = [1, 2, 3, 4, 5];
var evenNumbers = numbers.where((number) {
return number % 2 == 0;
}).toList();
print(evenNumbers); // [2, 4]
2
3
4
5
6
7
传递给where()的函数的返回值是bool值,满足条件的元素会被加入到新的List中。
也可以使用lambda表达式来简写:var evenNumbers = numbers.where((number) => number % 2 == 0).toList();
# 判断List中的元素是否有元素满足指定条件
可以使用any()方法,判断List中是否有元素满足指定的条件。
举个栗子:
判断List中是否有偶数
var numbers = [1, 2, 3, 4, 5];
var f = numbers.any((number) {
return number % 2 == 0;
});
print(f); // true
2
3
4
5
6
# 判断List中的元素是否都满足指定条件
any()方法是判断集合中是否有元素满足指定条件,every()方法是用来判断List中所有的元素都满足指定的条件。
举个栗子:
判断List中的元素是否都是偶数
var numbers = [1, 2, 3, 4, 5];
var f = numbers.every((number) {
return number % 2 == 0;
});
print(f); // false
2
3
4
5
6
7
# 6.2 Set
集合Set与List的区别:Set是一种不允许重复元素的容器类型,而且Set是无序的。
集合更重要的是用来做一些运算,例如求两个容器的交集、并集、差集等。
集合最主要的特点:
不支持重复的元素
内容是无序的,不能下标来访问元素
集合是可以被修改的
可以存储不同的数据类型
# 1 创建Set
// 方式一:创建一个空Set
Set<String> emptySet = {};
// 方式二:创建一个包含元素的集合
Set<String> fruits = {'apple', 'banana', 'orange'};
// 方式三:使用Set的构造函数来创建一个空集合
Set<String> fruits = Set<String>();
// 方式四:使用其他List或Set来创建
Set<String> fruits = Set<String>.from(['apple', 'banana', 'orange']);
Set<String> fruits = Set<String>.from({'apple', 'banana', 'orange'});
2
3
4
5
6
7
8
9
10
11
12
当然使用 var
来声明也是可以的。
var emptySet = {};
# 2 基础操作
# 添加元素
var numbers = {};
numbers.add(1);
numbers.add(2);
numbers.add(3);
2
3
4
# 访问元素
因为Set是无序的,所以无法通过下标来访问Set中的元素,如果想访问Set中的元素,只能通过遍历的方式来获取Set中的元素。
# 获取长度
var numbers = {1, 2, 3};
print(numbers.length); // 3
2
# 删除元素
var numbers = {1, 2, 3};
numbers.remove(2);
print(numbers); // {1, 3}
2
3
因为Set是无序的,所以无法通过下标来删除元素。
# 清空Set
var numbers = {1, 2, 3};
numbers.clear();
print(numbers); // {}
2
3
# 将Set转换为List
使用toList()方法可以将Set转换为List。
var numbers = {1, 2, 3};
List numList = numbers.toList();
print(numList); // [1, 2, 3]
2
3
# 3 遍历Set
当遍历一个 Set 时,您也可以使用多种方式,包括使用 for
循环、forEach()
方法、for-in
循环以及使用迭代器。下面我们将逐一介绍这些方法。
使用 for-in
循环
Set<String> fruits = {'apple', 'banana', 'orange'};
for (String fruit in fruits) {
print(fruit);
}
2
3
4
5
在这个示例中,我们使用 for-in
循环遍历了 Set 中的每个元素,并打印每个元素。
使用 forEach()
方法
forEach()
是 Dart 中 Set 类型的方法,它接受一个函数作为参数,并对 Set 中的每个元素都调用该函数。例如:
Set<String> fruits = {'apple', 'banana', 'orange'};
fruits.forEach((fruit) {
print(fruit);
});
2
3
4
5
在这个示例中,我们使用 forEach()
方法遍历了 Set 中的每个元素,并打印每个元素。
使用迭代器
Set 类型也实现了 Iterable
接口,因此您也可以使用迭代器来遍历 Set 中的元素。例如:
Set<String> fruits = {'apple', 'banana', 'orange'};
Iterator<String> iterator = fruits.iterator;
while (iterator.moveNext()) {
print(iterator.current);
}
2
3
4
5
6
在这个示例中,我们首先获取了 Set 的迭代器,并使用 while
循环和 moveNext()
方法遍历了 Set 中的每个元素,并使用 current
属性访问当前元素。
使用 for
循环
因为 Set 没有索引,所以您可以使用 Set.toList()
方法将 Set 转换为 List,并使用 List.length
属性确定 List 的长度。例如:
Set<String> fruits = {'apple', 'banana', 'orange'};
List<String> fruitsList = fruits.toList();
for (int i = 0; i < fruitsList.length; i++) {
print(fruitsList[i]);
}
2
3
4
5
6
在这个示例中,我们将 Set 转换为 List,然后使用 for
循环遍历 List 中的每个元素,并打印每个元素。
# 4 其他常用操作
因为List和Set都是容器,所以很多List有的操作Set也是有的。
# 判断Set是否为空
可以通过isEmpty()方法判断Set是否为空,通过isNotEmpty()方法判断Set是否不为空。
Set<int> numbers = {};
if (numbers.isEmpty) {
print("Set为空");
}
numbers = {1, 2, 3, 4, 5};
if (numbers.isNotEmpty) {
print("Set不为空");
}
2
3
4
5
6
7
8
9
# 检查包含某个元素
var numbers = {1, 2, 3};
print(numbers.contains(2)); // true
2
# 将Set中的元素拼接为字符串:
var numbers = {1, 2, 3};
var numberString = numbers.join(', ');
print(numberString); // '1, 2, 3'
2
3
Dart的Set类提供了许多有用的操作,例如:并集、交集和差集。
# 使用Set中的元素生成新的Set
和List一样,使用map方法,可以依次取出Set中的元素,然后进行处理,得到一个新的Set。
举个栗子:
将一个Set中的元素乘以2得到一个新的Set。
var numbers = {1, 2, 3};
var squaredNumbers = numbers.map((number) => number * 2).toSet();
print(squaredNumbers); // {2, 4, 6}
2
3
同样的where()、any()、every()方法,对Set都是适用的。
# 并集
使用union()方法将两个Set合并为一个Set。下面是一个示例:
var set1 = {1, 2, 3};
var set2 = {3, 4, 5};
var unionSet = set1.union(set2);
print(unionSet); // {1, 2, 3, 4, 5}
2
3
4
# 交集
使用intersection()方法获取两个Set的交集。下面是一个示例:
var set1 = {1, 2, 3};
var set2 = {3, 4, 5};
var intersectionSet = set1.intersection(set2);
print(intersectionSet); // {3}
2
3
4
# 差集
使用difference()方法获取两个Set的差集。下面是一个示例:
var set1 = {1, 2, 3};
var set2 = {3, 4, 5};
var differenceSet = set1.difference(set2);
print(differenceSet); // {1, 2}
2
3
4
# 6.3 Map
Map是一种键值对的数据结构,其中每个键对应一个值。
例如有一份数据:
姓名 | 成绩 |
---|---|
zhangsan | 94 |
lisi | 96 |
wangwu | 91 |
使用列表、集合的方式存储上面的数据是很不方便的。
而使用Map存储就很适合,可以将姓名作为key,成绩作为value。
{
"zhangsan": 94,
"lisi": 96,
"wangwu": 91
}
2
3
4
5
这样可以很容易通过姓名key得到对应的成绩value。
# 1 创建Map
map同样是使用 花括号{}
来定义的,但是存储的元素是一个一个的键值对。
// 方式一:创建一个空Map
Map<String, String> map = {};
// 方式二:创建一个包含元素的Map
Map<String, int> map = {'zhangsan': 94, 'lisi': 96, 'wangwu': 91};
// 方式三:使用Map的构造函数来创建一个空集合
Map<String, String> map = Map<String, String>();
2
3
4
5
6
7
8
Map<String, String> map
其中 <String, String>
分别表示 key
和 value
对应的数据类型。
当然,我们可以使用 var
来定义:
var emptyMap = Map<String, dynamic>();
# 2 基础操作
# 添加元素
var numbers = {};
numbers['one'] = 1;
numbers['two'] = 2;
numbers['three'] = 3;
print(numbers); // {one: 1, two: 2, three: 3}
2
3
4
5
# 访问元素
访问元素的时候,通过 key 来访问。
var numbers = {'one': 1, 'two': 2, 'three': 3};
print(numbers['two']); // 2
2
如果访问不存在的key,则得到结果为null。
# 获取长度
var numbers = {'one': 1, 'two': 2, 'three': 3};
print(numbers.length); // 3
2
# 删除元素
删除的时候,通过 key 来删除
var numbers = {'one': 1, 'two': 2, 'three': 3};
numbers.remove('two');
print(numbers); // {'one': 1, 'three': 3}
2
3
# 清空Map
var numbers = {'one': 1, 'two': 2, 'three': 3};
numbers.clear();
print(numbers); // {}
2
3
# 3 遍历操作
使用 for...in
循环
Map<String, int> studentMarks = {'Alice': 90, 'Bob': 80, 'Charlie': 85};
for (var entry in studentMarks.entries) {
var key = entry.key;
var value = entry.value;
print('Student $key got $value marks');
}
2
3
4
5
6
7
这个示例使用了 for...in
循环遍历 Map,其中的 entries
属性返回一个键值对的迭代器,然后在循环中使用 key
和 value
属性访问键和值。
使用 forEach()
方法
Map<String, int> studentMarks = {'Alice': 90, 'Bob': 80, 'Charlie': 85};
studentMarks.forEach((key, value) {
print('Student $key got $value marks');
});
2
3
4
5
这个示例使用了 forEach()
方法遍历 Map,其中的 lambda 表达式接收键和值,并在控制台打印出每个学生的分数。
使用 keys
或 values
属性
Map<String, int> studentMarks = {'Alice': 90, 'Bob': 80, 'Charlie': 85};
for (var key in studentMarks.keys) {
var value = studentMarks[key];
print('Student $key got $value marks');
}
for (var value in studentMarks.values) {
print('Student got $value marks');
}
2
3
4
5
6
7
8
9
10
这个示例使用了 keys
和 values
属性分别遍历 Map 的键和值,然后在循环中使用 key
或 value
变量访问相应的键或值。
# 4 其他常用操作
# 判断Map是否为空
可以通过isEmpty()方法判断Map是否为空,通过isNotEmpty()方法判断Map是否不为空。
Map numbers = {};
if (numbers.isEmpty) {
print("Map为空");
}
numbers = {'one': 1, 'two': 2, 'three': 3};
if (numbers.isNotEmpty) {
print("Map不为空");
}
2
3
4
5
6
7
8
9
# 检查包含某个键
var numbers = {'one': 1, 'two': 2, 'three': 3};
print(numbers.containsKey('two')); // true
2
# 检查包含某个值
var numbers = {'one': 1, 'two': 2, 'three': 3};
print(numbers.containsValue(2)); // true
2
# 获取Map中的所有键
var numbers = {'one': 1, 'two': 2, 'three': 3};
var keys = numbers.keys.toList();
print(keys); // ['one', 'two', 'three']
2
3
# 将Map中的键值对拼接为字符串
var numbers = {'one': 1, 'two': 2, 'three': 3};
var numberString = numbers.entries.map((entry) => '${entry.key}: ${entry.value}').join(', ');
print(numberString); // 'one: 1, two: 2, three: 3'
2
3