Dart 集合

一、Dart 内置三大集合

Dart 原生内置三种集合:ListSetMap

集合内部元素类型约束可通过泛型(Generics) 配置。

集合类型核心特性字面量标识
List有序、允许重复、下标索引[]
Set无序、元素唯一、无下标{}(需显式标注泛型才是 Set)
Map键值对存储、Key 唯一、Value 可重复{key: value}

二、List 列表(有序数组)

1. 基础定义与类型推断

  • Dart 中数组本质是 List 对象,字面量 [] 创建;
  • 类型自动推断,例如:var list = [1,2,3]List<int>,插入非 int 会报错;
  • 支持末尾尾随逗号,不影响语法,减少复制粘贴错误: dartvar list = ['Car', 'Boat', 'Plane',];

2. 基础操作

  1. 索引规则:从 0 开始,list.length - 1 为最后一位下标;
  2. 读取 / 修改元素:list[index]list[index] = 新值
  3. 获取长度:.length 属性;

例子

void main() {
	var list = [1,2,3];
	print(list.length);//输出元素个数 3
	print(list[1]);// 输出 2
	list[1] = 9; //修改第二个元素为9
	print(list[1]);//输出修改后的值 9
}Code language: Dart (dart)

3. 常量列表(编译期不可变)

字面量前加 const,运行时无法增删改元素:

void main() {
	var constantList = const [1,2,3];
	constantList[1] = 100; // 编译报错
}Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
Unsupported operation: Cannot modify an unmodifiable list
#0      UnmodifiableListMixin.[]= (dart:_internal/list.dart:89:5)
#1      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:4:14)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#3      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

三、Set 集合

无序唯一元素

一、Set 核心特性

  • 无序:元素没有固定下标,不能通过 [索引] 取值、修改
  • 元素唯一:自动去重,添加重复元素不会报错,但集合只会保留一份
  • 字面量标识:大括号 {}
  • 泛型约束:可限定存储单一类型,插入异类编译 / 运行报错

空 Set 与空 Map 区分(很容易出错)

{} 默认识别为 Map,创建空 Set 必须显式标注泛型

void main() {
	// 空 Set<String>
	var names = <String>{};
	Set<String> names2 = {}; // 等价写法

	// 无泛型标注,Dart 判定为 Map<dynamic, dynamic>
	var names3 = {};
}Code language: Dart (dart)
类型推断
void main() {
	// 自动推断 Set<String>
	var halogens = {'dog', 'cat', 'horse'};

	// 自动推断 Set<int>
	var nums = {1, 2, 6, 2}; // 重复 2 自动去重,最终 {1,2,6}

	// 混合类型,推断 Set<Object>(不推荐,失去类型校验)
	var mix = {1, "apple"};
}Code language: JavaScript (javascript)

自动推断后,如果插入不同各类型,会报错

void main() {
  // 字面量全为字符串,自动推断 Set<String>
  var animals = {'dog'};
  print(animals.runtimeType); // _CompactLinkedHashSet<String>

  // 正常添加同类型字符串,无报错
  animals.add('cat');
  animals.add('pig');
  print(animals); // {dog, cat, pig}
  
  // 报错:不能将 int 类型参数传递给 add 方法,方法要求 String
  animals.add(1); 
}Code language: Dart (dart)

2. 增删与长度

  • 添加单个:.add()
  • 批量添加:.addAll()
  • 获取元素总数:.length
var elements = <String>{};
elements.add('fluorine');
elements.addAll({'chlorine', 'bromine'});
print(elements.length); //3Code language: PHP (php)

3. 常量 Set

字面量前加 const,不可新增 / 删除元素:

final constantSet = const {'fluorine', 'chlorine'};
// constantSet.add('helium'); // 报错Code language: PHP (php)

四、Map 映射(键值对)

1. 基础特性
  • 存储 Key-Value 成对数据;
  • Key 全局唯一,Value 可重复;
  • Key、Value 支持任意对象类型;
  • 字面量格式 {key: value}
  • 类型自动推断:
void main() {
	var gifts = {'first': 'partridge'}; // 自动推断出是 Map<String, String> 
	
	var nobleGases = {2: 'helium'}; // 自动推断出是 Map<int, String>
}Code language: Dart (dart)
2. 两种创建方式
  • 字面量创建
var gifts = {'first': 'partridge'};  Code language: Dart (dart)
  • Map 构造函数创建(new 关键字可省略)
// 构造函数写法
var gifts = Map<String, String>();
gifts['first'] = 'partridge';Code language: JavaScript (javascript)
3. 增、查、长度
  1. 新增 / 覆盖键值:map[key] = value
  2. 根据 Key 取值:map[key];Key 不存在返回 null
  3. 获取键值对总数:.length
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // 新增
print(gifts['first']); //获取
print(gifts['fifth']);//获取
print(gifts.length); //获取长度 Code language: PHP (php)
4. 常量 Map

字面量前加 const,键值对不可修改:

final constantMap = const {2: 'helium', 10: 'neon'};
// constantMap[2] = 'Helium'; // 报错Code language: Dart (dart)

五、集合字面量增强元素

集合字面量内支持多种特殊语法,分为基础叶子元素流程控制元素两大类,用于简化集合构建。

  1. 叶子基础元素:单个表达式、Map 键值、空安全元素
  2. 流程控制元素:展开运算符、if 条件、for 循环、嵌套组合

1. 普通表达式元素

最基础写法,直接写表达式,结果插入集合,里面的第二个元素是通过表达式 2 * 3 算出来的 结果是 1 2 text

void main() {
	var list = [1, 2 * 3, 'text'];
	print(list); //[1, 6, text]
}Code language: PHP (php)

2. 键值元素

仅用于 Map 字面量,格式 key表达式 : value表达式,下面例子 第一个元素的key和value都是通过表达式算出来的。

void main() {
	var map = {1+1: 3*8, 'name': 'apple'};
	print(map); //{2: 24, name: apple}
}Code language: Dart (dart)

3. 空安全元素(Dart ≥3.8)

语法 ?表达式:表达式不为 null 才插入集合,null 直接忽略

List 中使用,a是null 最终a没插入,不会报错

int? a = null;
int? b = 3;
var items = [1, ?a, ?b, 5]; // [1, 3, 5]Code language: JavaScript (javascript)

Map 中使用(key/value 均可加?)

String? k = null;
int? v = null;
var m = {?k: ?v}; // key/value任意一个为null,整条键值对丢弃
Code language: JavaScript (javascript)

4. Spread element 展开运算符

① 普通展开 ...

将一个可迭代集合全部元素平铺插入,不能展开 null 集合

var a = [1,2,3];
var items = [0, ...a, 4]; // [0,1,2,3,4]Code language: JavaScript (javascript)
② 空安全展开 ...?

兼容 null 集合:集合为 null 时直接忽略,不报错;

集合非 null 但内部含 null 元素,仍会保留 null

List<int>? a = null;
var b = [1, null, 3];
var items = [0, ...?a, ...?b, 4]; // [0, 1, null, 3, 4]Code language: PHP (php)

规范:可空集合必须用 ...?,否则编译报错。

5. If element 条件元素

集合内直接写 if 分支,满足条件才插入对应内容,支持布尔判断、模式匹配 if-case、else

基础布尔判断
void main() {
	bool flag = true;
    var list = [0, if(flag) 1 else 99, 2];
	print(list); //[0, 1, 2]
}Code language: Dart (dart)
if-case 模式匹配(类型解构、数组解构)
void main() {
	Object data = 123;
	var info = [
	  if(data case int i) '数字:$i',
	  if(data case String s) '文本:$s'
	];
	print(info); //[数字:123]
}Code language: Dart (dart)

因为data是int 所以最终插入的是 数字:123 而不是文本 这个

6. For element 循环元素

集合内直接写 for 循环,循环生成多条元素,支持 for-in / 传统 for 三段式

var nums = [2,3,4];

// for-in
var list1 = [1, for(var n in nums) n*n, 7]; // [1,4,9,16,7]

// 三段式for
var list2 = [1, for(var x=5; x>2; x--) x, 7]; // [1,5,4,3,7]Code language: JavaScript (javascript)

7. 嵌套控制流

if、for、展开符可任意多层嵌套,等效其他语言列表推导式

例子,只保留偶数

var numbers = [1,2,3,4,5,6];
var items = [
  0,
  for(var n in numbers)
    if(n.isEven) n,
  8
]; // [0,2,4,6,8]Code language: JavaScript (javascript)

例子:嵌套 for + if + 展开

void main() {
	var ys = [1,2,3];
	var nest = [
	  ...[
		for(var x=0;x<2;x++)
		  for(var y in ys)
			if(x<y) x+y*10
	  ]
	];
	print(nest); //[10, 20, 30, 21, 31]
}Code language: Dart (dart)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注