dart:Iterable迭代器(类似Java顺序流)

是什么

Iterable<T> 表示可迭代的一系列元素(像一个“可以遍历”的序列)。

ListSet 都实现了 Iterable

Iterable 的方法(mapwhereexpand 等)返回惰性 Iterable,只有在真正迭代时才会计算(比如 for-intoList()forEach())。

Iterable 是同步集合(与用于异步事件序列的 Stream 不同)。

常见方法

汇总表

分类 方法 作用 示例
变换 (Transform) map(f) 把每个元素映射成新值,返回惰性 Iterable [1,2,3].map((e)=>e*2).toList()[2,4,6]
expand(f) 每个元素映射为一个 Iterable,然后扁平化 [[1,2],[3]].expand((e)=>e).toList()[1,2,3]
whereType<T>() 只保留指定类型的元素 [1,'a',2].whereType<int>().toList()[1,2]
过滤/切片 (Filter/Slice) where(cond) 按条件筛选 [1,2,3,4].where((e)=>e.isOdd).toList()[1,3]
take(n) 取前 n 个 [1,2,3,4].take(2).toList()[1,2]
skip(n) 跳过前 n 个 [1,2,3,4].skip(2).toList()[3,4]
takeWhile(cond) 从头开始,满足条件时取 [1,2,3,0,4].takeWhile((e)=>e>0).toList()[1,2,3]
skipWhile(cond) 从头开始,满足条件时跳过 [1,2,-1,3].skipWhile((e)=>e>0).toList()[-1,3]
followedBy
(iterable)
连接两个 Iterable [1,2].followedBy([3,4]).toList()[1,2,3,4]
查找/访问 (Find/Access) first 第一个元素 [1,2,3].first1
last 最后一个元素 [1,2,3].last3
single 要求只有一个元素时取它,否则抛异常 [42].single42
firstWhere
(cond)
找到第一个满足条件的元素 [1,2,3].firstWhere((e)=>e>1)2
判定 (Predicate) any(cond) 只要有一个满足条件就返回 true [1,2,3].any((e)=>e>2)true
every(cond) 所有都满足条件才返回 true [1,2,3].every((e)=>e>0)true
contains(val) 是否包含某个值 [1,2,3].contains(2)true
聚合 (Aggregate) reduce(f) 把所有元素两两合并 [1,2,3].reduce((a,b)=>a+b)6
fold(init,f) 从初始值开始累积 [1,2,3].fold(10,(a,b)=>a+b)16
join([sep]) 拼接为字符串 ['a','b','c'].join('-')"a-b-c"
转换/终止 (Convert
/Terminate)
toList() 转为 List(立即求值) [1,2,3].map((e)=>e*2).toList()[2,4,6]
toSet() 转为 Set(去重) [1,2,2,3].toSet(){1,2,3}
forEach(f) 遍历执行副作用(非惰性,立即执行) [1,2].forEach(print) → 输出 1\n2
cast<T>() 转换元素类型(运行时检查) ['a','b'].cast<String>()

变换(transform)

  • map((e) => ...):把每个元素转换成新值,返回 Iterable
  • expand((e) => Iterable):把每个元素映射成一个 Iterable,并扁平化。
var nums = [1,2,3];
var doubled = nums.map((n) => n * 2); // Iterable<int>
print(doubled.toList()); // [2,4,6]

var nested = [ [1,2], [3] ];
var flat = nested.expand((x) => x);
print(flat.toList()); // [1,2,3]

过滤(filter / slicing)

  • where((e) => cond):筛选符合条件的元素:
  • take(n) / skip(n):取前几个、跳过前几个。
  • takeWhile / skipWhile:按条件取/跳。
var odds = [1, 2, 3, 4].where((n) => n.isOdd);
print(odds.toList()); // [1, 3]

print([1,2,3,4,5].take(3).toList()); // [1,2,3]
print([1,2,3,4,5].skip(2).toList()); // [3,4,5]

print([1,2,3,0,4].takeWhile((e)=> e > 0).toList()); // [1,2,3]
print([1,2,-1,3,4].skipWhile((e)=> e > 0).toList()); // [-1,3,4]

查找 / 判定

first / last / single:取元素

  • single:要求只有一个元素时取它,否则抛异常

firstWhere(cond):找到第一个满足条件的元素

any :只要有一个满足条件就返回 true

every:所有都满足条件才返回 true

contains:包含检测。

print([10,20,30].first);  // 10
print([10,20,30].last);   // 30
print([42].single);       // 42

print([1,2,3,4].firstWhere((n)=>n>2)); // 3

print([1,2,3].any((n)=>n>2));  // true
print([1,2,3].every((n)=>n>0)); // true

print([1,2,3].contains(2)); // true

聚合 / 归约

reduce((a,b)=>...):两两合并,需至少一个元素。

fold(initial, (acc,e)=>...):从初始值开始累积。

join(separator):拼接为字符串。

print([1,2,3,4].reduce((a,b)=>a+b)); // 10

print([1,2,3].fold(10, (a,b)=>a+b)); // 16  (10+1+2+3)

print(['a','b','c'].join('-')); // a-b-c

转换 / 终止

  • toList() / toSet():有限并立即求值,生成集合。
  • forEach((e)=>...):迭代副作用(终止操作)。
  • length:注意:对非 ListIterablelength 可能需要遍历一次(O(n))。
var list = [1,2,2,3].toList(); // [1,2,2,3]
var set  = [1,2,2,3].toSet();  // {1,2,3}

[1,2,3].forEach((e)=>print("num=$e"));
// 输出:
// num=1
// num=2
// num=3

print([1,2,3].length); // 3

惰性(lazy)示例

var it = [1,2,3].map((e) {
  print('map $e');
  return e * 2;
});

print('created'); // 这里不会 print map ...
for (var v in it) {
  print('value $v');
}

输出顺序会显示 map 1value 2 … —— 映射函数直到迭代时才执行。

toList() 会立刻触发全部计算并把结果缓存到内存:

var list = it.toList(); // 此处全部执行并返回 List

自定义 Iterable

Iterator<T> 有两个主要成员:bool moveNext()T get current

yield

sync\* + yield(最简便) —— 返回 Iterable,且是惰性的:

Iterable<int> range(int start, int end) sync* {
  for (int i = start; i < end; i++) {
    yield i;
  }
}

(实际开发中 sync* 更常用也更简洁。)

无限序列(lazy 的实用场景)

使用 sync* 你可以写出无限序列(注意在消费端要限制):

Iterable<int> naturals() sync* {
  int i = 0;
  while (true) yield i++;
}

var firstTen = naturals().take(10).toList(); // 安全地只取 10 个

实现 Iterable / Iterator

实现 Iterable / Iterator(更底层) 或 使用 IterableBase / IterableMixin(dart:collection)简化实现:

class Range extends Iterable<int> {
  final int start, end;
  Range(this.start, this.end);

  @override
  Iterator<int> get iterator => _RangeIterator(start, end);
}

class _RangeIterator implements Iterator<int> {
  final int _end;
  int _current;
  _RangeIterator(this._current, this._end);

  @override
  int get current => _current;

  @override
  bool moveNext() {
    if (_current < _end) {
      _current++;
      return true;
    }
    return false;
  }
}

×

喜欢就点赞,疼爱就打赏