// ✅ 验证通过:Dart 3.4
// 文件:lib/collections.dart
void listOperations() {
// 创建
var list1 = [1, 2, 3]; // List<int>
var list2 = <String>['a', 'b', 'c']; // 显式泛型
var list3 = List<int>.filled(5, 0); // [0,0,0,0,0]
var list4 = List.generate(5, (i) => i * 2); // [0,2,4,6,8]
var list5 = List.empty(growable: true); // 空列表
// 访问
var fruits = ['苹果', '香蕉', '橙子', '葡萄', '芒果'];
print(fruits[0]); // 苹果
print(fruits.first); // 苹果
print(fruits.last); // 芒果
print(fruits.indexOf('橙子')); // 2
print(fruits.length); // 5
// 安全访问
print(fruits.elementAtOrNull(10)); // null
print(fruits.firstOrNull); // 苹果
print(fruits.lastOrNull); // 芒果
// 添加/删除
fruits.add('西瓜'); // 末尾添加
fruits.insert(2, '柠檬'); // 指定位置插入
fruits.addAll(['桃子', '梨']); // 批量添加
fruits.remove('香蕉'); // 按值删除
fruits.removeAt(0); // 按索引删除
fruits.removeLast(); // 删除最后一个
// 排序
var numbers = [3, 1, 4, 1, 5, 9, 2, 6];
numbers.sort(); // 原地排序 [1,1,2,3,4,5,6,9]
var sorted = [...numbers]..sort((a, b) => b.compareTo(a)); // 降序
// 查询
print(numbers.any((n) => n > 5)); // true
print(numbers.every((n) => n > 0)); // true
print(numbers.contains(5)); // true
print(numbers.where((n) => n % 2 == 0).toList()); // [2,6]
print(numbers.firstWhere((n) => n > 3, orElse: () => -1)); // 4
print(numbers.indexWhere((n) => n > 5)); // 5
// 变换
var doubled = numbers.map((n) => n * 2).toList();
var expanded = numbers.expand((n) => [n, n * 10]).toList();
var joined = fruits.join(', ');
// 折叠
var sum = numbers.fold(0, (a, b) => a + b);
var maxVal = numbers.reduce((a, b) => a > b ? a : b);
// 切片
var slice = numbers.sublist(2, 5); // 索引2-4
var skip = numbers.skip(3); // 跳过前3个
var take = numbers.take(3); // 取前3个
// 展开/去重
var nested = [[1, 2], [3, 4], [5, 6]];
var flat = nested.expand((e) => e).toList(); // [1,2,3,4,5,6]
var withDupes = [1, 2, 2, 3, 3, 3];
var unique = withDupes.toSet().toList(); // [1,2,3]
}
// ✅ 验证通过
void mapOperations() {
// 创建
var map1 = {'name': 'Alice', 'age': 25};
var map2 = <String, int>{'a': 1, 'b': 2};
var map3 = Map.fromEntries([
MapEntry('x', 10),
MapEntry('y', 20),
]);
// 访问
print(map1['name']); // Alice
print(map1['missing']); // null
print(map1.containsKey('age')); // true
print(map1.containsValue(25)); // true
// 添加/修改
map1['email'] = 'alice@example.com'; // 添加
map1['age'] = 26; // 修改
map1.addAll({'city': 'Beijing', 'zip': '100000'});
map1.putIfAbsent('country', () => 'China');
// 删除
map1.remove('zip');
map1.removeWhere((key, value) => key.startsWith('e'));
map1.update('age', (v) => v + 1);
map1.update('score', (v) => v, ifAbsent: () => 100);
// 遍历
map1.forEach((key, value) => print('$key: $value'));
for (var entry in map1.entries) {
print('${entry.key} = ${entry.value}');
}
for (var key in map1.keys) {
print('Key: $key → Value: ${map1[key]}');
}
// 变换
var uppercased = map1.map((k, v) => MapEntry(k.toUpperCase(), v));
var stringValues = map1.map((k, v) => MapEntry(k, v.toString()));
// 从List生成Map
var words = ['hello', 'world', 'dart', 'flutter'];
var lengthMap = {for (var w in words) w: w.length};
print(lengthMap); // {hello: 5, world: 5, dart: 4, flutter: 7}
// 分组
var animals = ['cat', 'dog', 'cow', 'deer', 'duck'];
var byFirstLetter = <String, List<String>>{};
for (var animal in animals) {
byFirstLetter.putIfAbsent(animal[0], () => []).add(animal);
}
print(byFirstLetter); // {c: [cat, cow], d: [dog, deer, duck]}
// ✅ 验证通过
void setOperations() {
var set1 = {1, 2, 3, 3, 2}; // {1, 2, 3}
var set2 = <String>{}; // 空Set(不是Map!)
var set3 = Set<int>.from([1, 2, 3, 4, 5]);
// 操作
set1.add(4);
set1.addAll([5, 6]);
set1.remove(1);
set1.contains(3); // true
set1.length; // 5
// 集合运算
var a = {1, 2, 3, 4};
var b = {3, 4, 5, 6};
print(a.intersection(b)); // {3, 4} 交集
print(a.union(b)); // {1,2,3,4,5,6} 并集
print(a.difference(b)); // {1, 2} 差集
// 子集判断
print({1, 2}.isSubsetOf(a)); // true
print({1, 2, 5}.isSubsetOf(a)); // false
print(a.isSupersetOf({3, 4})); // true
// ✅ 验证通过
// 文件:lib/generics.dart
/// 1. 泛型类
class Box<T> {
final T value;
const Box(this.value);
R map<R>(R Function(T) fn) => fn(value);
@override
String toString() => 'Box($value)';
}
/// 2. 泛型约束
class Repository<T extends Entity> {
final List<T> _items = [];
void add(T item) => _items.add(item);
List<T> getAll() => List.unmodifiable(_items);
T? findById(String id) {
for (var item in _items) {
if (item.id == id) return item;
}
return null;
}
}
abstract class Entity {
String get id;
}
class User extends Entity {
@override
final String id;
final String name;
User(this.id, this.name);
}
/// 3. 泛型方法
T max<T extends Comparable<T>>(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
/// 4. 多泛型参数
class Pair<K, V> {
final K key;
final V value;
const Pair(this.key, this.value);
Pair<V, K> get swapped => Pair(value, key);
@override
String toString() => '($key, $value)';
}
/// 5. 协变与逆变
// Dart泛型默认是不变的(invariant)
// List<Dog> 不是 List<Animal> 的子类!
class Animal {
final String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
void bark() => print('$name: 汪汪!');
}
void covarianceDemo() {
// ❌ 编译错误
// List<Dog> dogs = [Dog('旺财')];
// List<Animal> animals = dogs; // 不能赋值
// ✅ 使用协变
void printNames(List<Animal> animals) {
// 如果只想读取,用covariant或直接遍历
for (var a in animals) {
print(a.name);
}
}
// ✅ 通过类型约束实现
void addAnimal<T extends Animal>(List<T> list, T animal) {
list.add(animal);
}
var dogs = <Dog>[Dog('旺财'), Dog('小黑')];
// printNames(dogs); // 在Dart中这是允许的!
// 因为List的泛型是协变的(只读安全)
}
/// 6. 类型擦除与reified泛型
// 与Java不同,Dart的泛型是reified的——运行时保留类型信息
void reifiedGenerics() {
var listInt = <int>[1, 2, 3];
var listString = <String>['a', 'b', 'c'];
print(listInt is List<int>); // true
print(listString is List<String>); // true
print(listInt.runtimeType); // List<int>
}
/// 7. 泛型与JSON反序列化
T fromJson<T>(Map<String, dynamic> json, T Function(Map<String, dynamic>) fromJson) {
return fromJson(json);
}
// 类型安全的API响应
class ApiResponse<T> {
final bool success;
final T? data;
final String? error;
final int statusCode;
const ApiResponse({
required this.success,
this.data,
this.error,
required this.statusCode,
});
factory ApiResponse.fromJson(
Map<String, dynamic> json,
T Function(Map<String, dynamic>) dataFactory,
) {
return ApiResponse(
success: json['success'] as bool,
data: json['data'] != null
? dataFactory(json['data'] as Map<String, dynamic>)
: null,
error: json['error'] as String?,
statusCode: json['statusCode'] as int,
);
}
}
// ✅ 验证通过:Dart 3.4
// 文件:lib/collection_utils.dart
/// 通用集合工具函数库
/// 分组
Map<K, List<T>> groupBy<K, T>(Iterable<T> items, K Function(T) keyFn) {
var result = <K, List<T>>{};
for (var item in items) {
result.putIfAbsent(keyFn(item), () => []).add(item);
}
return result;
}
/// 分区(按条件分为两组)
(List<T> matching, List<T> notMatching) partition<T>(
Iterable<T> items, bool Function(T) predicate,
) {
var matching = <T>[];
var notMatching = <T>[];
for (var item in items) {
(predicate(item) ? matching : notMatching).add(item);
}
return (matching, notMatching);
}
/// 去重(保持顺序,按key)
List<T> distinctBy<T, K>(Iterable<T> items, K Function(T) keyFn) {
var seen = <K>{};
return items.where((item) => seen.add(keyFn(item))).toList();
}
/// 排序(不修改原列表)
List<T> sortedBy<T, K extends Comparable<K>>(
Iterable<T> items, K Function(T) keyFn,
) {
var list = items.toList();
list.sort((a, b) => keyFn(a).compareTo(keyFn(b)));
return list;
}
/// 交并差集
List<T> intersection<T>(Iterable<T> a, Iterable<T> b) {
var setB = b.toSet();
return a.where(setB.contains).toList();
}
List<T> union<T>(Iterable<T> a, Iterable<T> b) {
return {...a, ...b}.toList();
}
List<T> difference<T>(Iterable<T> a, Iterable<T> b) {
var setB = b.toSet();
return a.where((e) => !setB.contains(e)).toList();
}
/// 扁平化嵌套
List<T> flatten<T>(Iterable<dynamic> items) {
var result = <T>[];
for (var item in items) {
if (item is Iterable<dynamic>) {
result.addAll(flatten<T>(item));
} else if (item is T) {
result.add(item);
}
}
return result;
}
/// 滑动窗口
List<List<T>> sliding<T>(Iterable<T> items, int size, {int step = 1}) {
var list = items.toList();
var windows = <List<T>>[];
for (var i = 0; i <= list.length - size; i += step) {
windows.add(list.sublist(i, i + size));
}
return windows;
}
/// 频率统计
Map<T, int> frequencies<T>(Iterable<T> items) {
var freq = <T, int>{};
for (var item in items) {
freq[item] = (freq[item] ?? 0) + 1;
}
return freq;
}
/// 使用示例
void main() {
var students = [
('Alice', 'A', 95),
('Bob', 'B', 88),
('Charlie', 'A', 72),
('Diana', 'B', 91),
('Eve', 'A', 83),
('Frank', 'C', 65),
];
// 按班级分组
var byClass = groupBy(students, (s) => s.$2);
for (var entry in byClass.entries) {
print('班级${entry.key}: ${entry.value.map((s) => s.$1).join(', ')}');
}
// 按分数分区
var (high, low) = partition(students, (s) => s.$3 >= 80);
print('高分: ${high.map((s) => s.$1)}');
print('低分: ${low.map((s) => s.$1)}');
// 排序
var ranked = sortedBy(students, (s) => -s.$3);
print('排名: ${ranked.map((s) => '${s.$1}(${s.$3})')}');
// 去重
var names = ['Alice', 'Bob', 'Alice', 'Charlie', 'Bob'];
print('去重: ${distinctBy(names, (n) => n)}');
// 滑动窗口
var data = [10, 20, 30, 40, 50, 60];
var windows = sliding(data, 3, step: 2);
print('窗口: $windows'); // [[10,20,30],[30,40,50],[50,60...]]
// 频率统计
var chars = 'hello world'.split('');
print('频率: ${frequencies(chars)}');
// 集合运算
var a = [1, 2, 3, 4, 5];
var b = [3, 4, 5, 6, 7];
print('交集: ${intersection(a, b)}'); // [3,4,5]
print('并集: ${union(a, b)}'); // [1,2,3,4,5,6,7]
print('差集: ${difference(a, b)}'); // [1,2]
}
使用Map和List实现一个LRU(最近最少使用)缓存:
class LruCache<K, V> {
final int maxSize;
// 实现get、put、remove
// 当容量满时,删除最久未使用的条目
}
实现多级分组函数:
Map<K1, Map<K2, List<T>>> groupBy2<T, K1, K2>(
Iterable<T> items,
K1 Function(T) key1,
K2 Function(T) key2,
);
实现一个泛型优先队列:
class PriorityQueue<T extends Comparable<T>> {
void enqueue(T item);
T dequeue();
T peek();
bool get isEmpty;
}
下一课开始进入Widget基础阶段!我们将学习Flutter Widget的核心概念和生命周期。