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

相关推荐
小兔崽子去哪了12 分钟前
微信小程序入门
前端·vue.js·微信小程序
独立开阀者_FwtCoder15 分钟前
# 白嫖千刀亲测可行——200刀拿下 Cursor、V0、Bolt和Perplexity 等等 1 年会员
前端·javascript·面试
不和乔治玩的佩奇22 分钟前
【 React 】useState (温故知新)
前端
那小孩儿22 分钟前
?? 、 || 、&&=、||=、??=这些运算符你用对了吗?
前端·javascript
七月十二25 分钟前
[微信小程序]对接sse接口
前端·微信小程序
小七_雪球27 分钟前
Permission denied"如何解决?详解GitHub SSH密钥认证流程
前端·github
野原猫之助28 分钟前
tailwind css在antd组件中使用不生效
前端
没资格抱怨35 分钟前
如何在vue3项目中使用 AbortController取消axios请求
前端·javascript·vue.js
掘金酱39 分钟前
😊 酱酱宝的推荐:做任务赢积分“拿”华为MatePad Air、雷蛇机械键盘、 热门APP会员卡...
前端·后端·trae
热爱编程的小曾1 小时前
sqli-labs靶场 less 11
前端·css·less