Dart 语言 Stream操作符与聚合函数实践

Dart阿木 发布于 27 天前 5 次阅读


Dart 语言 Stream 操作符与聚合函数实践

在 Dart 语言中,Stream 是一种异步数据序列,它允许我们以流的方式处理数据。Stream 操作符和聚合函数是 Stream API 中的核心组成部分,它们使得我们可以对 Stream 中的数据进行高效的转换、过滤和汇总。本文将围绕 Dart 语言中的 Stream 操作符与聚合函数进行实践,通过一系列的示例代码,帮助读者深入理解并掌握这些概念。

Stream 操作符

Stream 操作符是 Dart 中用于处理 Stream 数据的一系列函数。它们可以连接多个操作,形成一个数据处理管道。以下是一些常用的 Stream 操作符:

1. map

`map` 操作符用于将 Stream 中的每个元素映射到另一个值。它接收一个函数作为参数,该函数定义了如何将原始元素转换为新的元素。

dart

Stream<int> numbers = Stream.fromIterable([1, 2, 3, 4, 5]);


Stream<String> stringNumbers = numbers.map((number) => '$number');


stringNumbers.listen((number) => print(number));


2. where

`where` 操作符用于过滤 Stream,只允许满足特定条件的元素通过。

dart

Stream<int> numbers = Stream.fromIterable([1, 2, 3, 4, 5]);


Stream<int> evenNumbers = numbers.where((number) => number.isEven);


evenNumbers.listen((number) => print(number));


3. debounce

`debounce` 操作符用于在指定的时间内,如果 Stream 中有多个连续的元素,则只发出最后一个元素。

dart

Stream<String> input = Stream.periodic(Duration(seconds: 1), (count) => 'Input $count');


Stream<String> debouncedInput = input.debounce(Duration(seconds: 2));


debouncedInput.listen((input) => print(input));


4. expand

`expand` 操作符类似于 `map`,但它接收一个函数,该函数返回一个 Stream,然后将这些 Stream 连接起来。

dart

Stream<int> numbers = Stream.fromIterable([1, 2, 3, 4, 5]);


Stream<int> expandedNumbers = numbers.expand((number) => Stream.fromIterable([number, number 2]));


expandedNumbers.listen((number) => print(number));


聚合函数

聚合函数用于对 Stream 中的数据进行汇总。以下是一些常用的聚合函数:

1. fold

`fold` 操作符用于将 Stream 中的元素与一个初始值进行累积操作,返回一个单一的值。

dart

Stream<int> numbers = Stream.fromIterable([1, 2, 3, 4, 5]);


int sum = numbers.fold(0, (previousValue, element) => previousValue + element);


print(sum); // 输出 15


2. reduce

`reduce` 操作符与 `fold` 类似,但它返回一个 Stream,而不是单个值。

dart

Stream<int> numbers = Stream.fromIterable([1, 2, 3, 4, 5]);


Stream<int> reducedNumbers = numbers.reduce((previousValue, element) => previousValue + element);


reducedNumbers.listen((sum) => print(sum)); // 输出 15


3. every

`every` 操作符用于检查 Stream 中的所有元素是否都满足某个条件。

dart

Stream<int> numbers = Stream.fromIterable([1, 2, 3, 4, 5]);


bool allEven = numbers.every((number) => number.isEven);


print(allEven); // 输出 false


4. any

`any` 操作符用于检查 Stream 中是否存在至少一个元素满足某个条件。

dart

Stream<int> numbers = Stream.fromIterable([1, 2, 3, 4, 5]);


bool hasEven = numbers.any((number) => number.isEven);


print(hasEven); // 输出 true


实践案例

以下是一个使用 Stream 操作符和聚合函数的实践案例,我们将创建一个简单的用户输入处理程序,该程序将统计用户输入的字符数,并在用户停止输入后输出总字符数。

dart

import 'dart:async';

void main() {


StreamController<String> inputController = StreamController<String>();


Stream<String> input = inputController.stream;

Stream<int> characterCount = input


.expand((text) => text.split('')) // 将输入分割成字符


.map((char) => char.length) // 获取每个字符的长度


.fold(0, (previousValue, element) => previousValue + element); // 累加字符长度

input.listen((text) => print('Received input: $text'));


characterCount.listen((count) => print('Total characters: $count'));

// 模拟用户输入


input.add('Hello');


input.add(' World!');


input.close(); // 停止输入


}


在这个案例中,我们创建了一个 `StreamController` 来接收用户输入,然后使用 `expand` 将输入分割成字符,`map` 获取每个字符的长度,最后使用 `fold` 累加字符长度。当用户停止输入时,`input.close()` 被调用,Stream 结束,`characterCount` 中的 `listen` 回调被触发,输出总字符数。

总结

Stream 操作符和聚合函数是 Dart 语言中处理异步数据流的重要工具。通过本文的实践案例,我们学习了如何使用这些操作符和函数来转换、过滤和汇总 Stream 中的数据。掌握这些概念对于编写高效、可维护的 Dart 代码至关重要。