Dart 中的聚合类型与容器类型详解

Dart 中的聚合类型与容器类型详解

在 Dart 中,聚合类型(Aggregate Types) 和 容器类型(Container Types) 是指能够存储和管理一组数据的类型。它们的核心功能是将多个元素组合成一个整体,便于统一操作和管理。尽管这两个术语有时会被混用,但可以这样理解:

  • 聚合类型:强调数据结构的"聚合"特性,即由多个元素组合而成的类型(如数组、列表、集合等)。
  • 容器类型:更广泛的概念,指能够"容纳"其他对象或数据的结构(如列表、集合、映射、队列等)。

Dart 提供了多种容器类型,最核心的包括 List、Set、Map ,以及一些衍生类型(如 Queue)。以下是详细说明:

1. 核心容器类型详解

1.1 List(列表)

List 是一种有序、可重复、可变 的集合,通过索引访问元素,类似于数组。

特性
  • 有序性 :元素按插入顺序存储,可通过索引(从 0 开始)访问。
  • 可重复性:允许存储重复元素。
  • 可变性 :默认支持增删改操作,但可通过 const 声明不可变列表。
声明与初始化
dart 复制代码
// 可变列表
List<int> numbers = [1, 2, 3]; // 显式类型
var strings = <String>['a', 'b', 'c']; // 类型推导

// 不可变列表(使用 const)
const immutableList = const [4, 5, 6]; // 无法修改
常用操作
方法/属性 说明 示例
add(element) 在列表末尾添加元素。 numbers.add(4); → [1, 2, 3, 4]
insert(index, element) 在指定位置插入元素。 numbers.insert(0, 0); → [0, 1, 2, 3, 4]
remove(element) 移除第一个匹配的元素。 numbers.remove(2); → [1, 3, 4]
removeAt(index) 移除指定索引的元素。 numbers.removeAt(0); → [2, 3, 4]
length 获取列表长度。 print(numbers.length); → 4
[] 通过索引访问或修改元素。 numbers[0] = 10; → [10, 1, 2, 3]
addAll(iterable) 将另一个集合的元素追加到列表末尾。 numbers.addAll([5, 6]); → [1, 2, 3, 5, 6]

1.2 Set(集合)

Set 是一种无序、不可重复、可变的集合,用于存储唯一元素。

特性
  • 无序性:元素存储顺序不固定,遍历时可能与插入顺序不同。
  • 唯一性:不允许重复元素。
  • 可变性 :默认支持增删操作,但可通过 const 声明不可变集合。
声明与初始化
dart 复制代码
// 可变集合
Set<String> fruits = {'apple', 'banana', 'orange'}; // 显式类型
var uniqueNumbers = <int>{1, 2, 3}; // 类型推导

// 不可变集合(使用 const)
const immutableSet = const {'apple', 'banana'}; // 无法修改
常用操作
方法/属性 说明 示例
add(element) 添加元素,若已存在则返回 false。 fruits.add('grape'); → {'apple', 'banana', 'orange', 'grape'}
remove(element) 移除指定元素。 fruits.remove('banana'); → {'apple', 'orange', 'grape'}
contains(element) 检查元素是否存在。 fruits.contains('apple'); → true
addAll(iterable) 合并另一个集合的元素(重复元素会被忽略)。 fruits.addAll({'apple', 'mango'}); → {'apple', 'mango', ...}

1.3 Map(映射)

Map 是一种键值对(Key-Value) 的无序集合,通过键快速查找值。键必须唯一,但值可以重复。

特性
  • 无序性:元素存储顺序不固定。
  • 唯一性:键必须唯一,但值可以重复。
  • 快速查找:通过键查找值的时间复杂度为 O(1)。
声明与初始化
dart 复制代码
// 可变映射
Map<String, int> ageMap = {'Alice': 30, 'Bob': 25}; // 显式类型
var scores = <String, double>{'Math': 90.5, 'Science': 85.0}; // 类型推导

// 不可变映射(使用 const)
const immutableMap = const {'name': 'Alice', 'age': 30}; // 无法修改
常用操作
方法/属性 说明 示例
putIfAbsent(key, ifAbsent) 如果键不存在,则添加键值对;否则返回现有值。 ageMap.putIfAbsent('Charlie', () => 20); → 新增键 'Charlie'
remove(key) 移除指定键的条目。 ageMap.remove('Bob'); → 移除键 'Bob'
containsKey(key) 检查是否存在指定键。 ageMap.containsKey('Alice'); → true
addAll(map) 合并另一个 Map 的键值对(重复键会被覆盖)。 ageMap.addAll({'Alice': 35}); → 键 'Alice' 的值被更新为 35

2. 其他容器类型

2.1 Queue(队列)

Queue 是一种先进先出(FIFO)的容器,需导入 dart:collection:

dart 复制代码
import 'dart:collection';

void main() {
  Queue<int> queue = Queue();
  queue.add(1);
  queue.add(2);
  print(queue.removeFirst()); // 输出 1
  print(queue.first); // 输出 2
}

3. 容器类型的共同特性

所有容器类型(List、Set、Map)都实现了 Iterable 接口,支持以下操作:

  • 遍历 :

    dart 复制代码
    numbers.forEach((num) => print(num));
    for (var fruit in fruits) { ... }
  • 转换与筛选 :

    dart 复制代码
    var doubled = numbers.map((x) => x * 2); // [2, 4, 6, 8]
    var even = numbers.where((x) => x.isEven); // 过滤偶数
    var sum = numbers.reduce((a, b) => a + b); // 求和

4. 对比表格:快速选择容器类型

类型 有序性 可重复性 存储形式 适用场景
List ✅ ✅ 索引访问 需要有序、可重复的元素集合
Set ❌ ❌ 唯一元素集合 需要去重的场景
Map ❌ ✅(值可重复) 键值对(键唯一) 需要通过键快速查找值的场景
Queue ✅ ✅ 先进先出(FIFO) 需要队列操作的场景(如任务队列)

5. 注意事项

  1. 不可变容器:

    • 通过 const 声明的容器(如 const List、const Set)无法修改。
    • 示例:const colors = const ['red', 'green', 'blue'];
  2. 类型安全:

    • 始终使用类型注解(如 List<int>)确保数据一致性。
  3. 性能考量:

    • List 的索引访问是 O(1),但频繁插入/删除中间元素可能效率较低。
    • Map 的键查找是 O(1),适合需要快速查找的场景。

6. 示例代码

dart 复制代码
void main() {
  // List 示例
  List<int> numbers = [1, 2, 3];
  numbers.add(4);
  print(numbers[0]); // 输出 1

  // Set 示例
  Set<String> fruits = {'apple', 'banana'};
  fruits.add('grape');
  print(fruits.contains('apple')); // true

  // Map 示例
  Map<String, int> ageMap = {'Alice': 30};
  ageMap['Bob'] = 25;
  print(ageMap['Alice']); // 30
}

总结

  • 聚合类型 和 容器类型 在 Dart 中通常指能存储一组数据的结构,核心类型为 List、Set、Map。
  • 根据需求选择:
    • 有序、可重复 → List。
    • 去重、无序 → Set。
    • 键值对快速查找 → Map。
  • 充分利用容器的共同特性(如迭代、转换)和不可变性,提升代码健壮性。

相关推荐
SoaringHeart几秒前
Flutter 查缺补漏:@JsonKey 属性全解,让模型层不再被后端字段牵着走
flutter
Csvn14 分钟前
构建工具
前端
FRing0344 分钟前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
kyriewen3 小时前
Skills 榜前 10 我全装了:只有 3 个能直接用
前端·javascript·程序员
IT_陈寒3 小时前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫4 小时前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus4 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude
孟陬5 小时前
Foobar 技术周刊#159:当看不懂代码时,如何高效排障调试。脏页陷阱:一条只读查询,写入数 TB 数据。推测解码:大模型加速利器
前端·人工智能·后端
Zhao-Jichao5 小时前
AI Prompting for Everyone 课程笔记 - P17 图像生成 Imaging Generation
前端
Highcharts.js6 小时前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化