写点什么

dart 系列之: 集合使用最佳实践

作者:程序那些事
  • 2022 年 2 月 14 日
  • 本文字数:1954 字

    阅读完需:约 6 分钟

dart系列之:集合使用最佳实践

简介

dart 中有四种集合,分别是 Set,List,Map 和 queues。这些集合在使用中需要注意些什么呢?什么样的使用才是最好的使用方法呢?一起来看看吧。

使用字面量创建集合

对于常用的 Set,Map 和 List 三个集合来说,他们是有自己的无参构造函数的:


  factory Set() = LinkedHashSet<E>;  external factory Map();
@Deprecated("Use a list literal, [], or the List.filled constructor instead") external factory List([int? length]);
复制代码


可以看到 Set 和 Map 是可以使用构造函数的。但是对于 List 来说,无参的构造函数已经不推荐使用了。


对于 Set 和 Map 来说,可以这样构造:


var studentMap = Map<String, Student>();var ages = Set<int>();
复制代码


但是 dart 官方推荐直接使用字面量来创建这些集合,如下所示:


var studentMap = <String, Student>{};var ages = <int>{};
复制代码


为什么呢?这是因为 dart 中的字面量集合是非常强大的。可以通过扩展运算符,if 和 for 语句对集合进行构造和扩展,如下所示:


var studentList = [  ...list1,  student1,  ...?list2,  for (var name in list3)    if (name.endsWith('jack'))      name.replaceAll('jack', 'mark')];
复制代码

不要使用.length 来判断集合是否为空

对应 dart 的可遍历集合来说,这些集合并没有存储集合的长度信息,所以如果你调用集合的.length 方法,可能会导致集合的遍历,从而影响性能。


注意 Set 和 List 是可遍历的,而 Map 是不可遍历的。


所以,我们需要调用集合的.isEmpty 和 .isNotEmpty 方法来判断集合是否为空,这样速度更快。


if (studentList.isEmpty) print('it is empty');if (studentList.isNotEmpty) print('it is not empty');
复制代码

可遍历对象的遍历

对应 Set 和 List 这两个可遍历的集合来说,有两种遍历方法,可以通过调用 forEach() 方法或者 for-in 来进行遍历,如下所示:


for (final student in studentList) {  ...}
复制代码


studentList.forEach((student) {  ...});
复制代码


这两种方法中,dart 推荐使用 for in 的写法。


当然,如果你想将现有的 function 应用在集合中的每个元素中,forEach 也是可以的:


studentList.forEach(print);
复制代码


注意,因为 Map 是不可遍历的,所以上面的规则对 Map 并不适用。

List.from 和 iterable.toList

可遍历对象可以通过调用 toList 将其转换成为 List,同样的 List.from 也可以将可遍历对象转换成为 List。


那么两者有什么区别呢?


var list1 = iterable.toList();var list2 = List.from(iterable);
复制代码


两者的区别是 iterable.toList 并不会改变 list 中数据的类型,而 List.from 会. 举个例子:


// Creates a List<String>:var studentList = ['jack', 'mark', 'alen'];
// Prints "List<String>":print(studentList.toList().runtimeType);
// Prints "List<dynamic>":print(List.from(studentList).runtimeType);
复制代码


当然,你也可以使用 List<T>.from 来强制对创建出来的 List 进行类型转换。


List<String>.from(studentList)
复制代码

where 和 whereType

对于可遍历对象来说,两个过滤集合中元素的方法,他们是 where 和 whereType。


比如,我们需要过滤 List 中的字符串,则可以这样写:


var studentList = ['jack', 'ma', 18, 31];var students1 = studentList.where((e) => e is String);var students2 = studentList.whereType<String>();
复制代码


看上去两者没有太大的区别,都可以得到应有的结果。但是两者事实上还是有区别的,因为对应 where 来说,返回的是一个 Iterable<Object>,所以上面的例子中,如果我们真的需要返回 String,还需要对返回结果进行 case:


var students1 = studentList.where((e) => e is String).cast<String>();;
复制代码


所以,如果你要返回特定的对象时候,记得使用 whereType。

避免使用 cast

cast 通常用来对集合中的元素进行类型转换操作,但是 cast 的性能比较低,所以在万不得已的情况下,一定要避免使用 cast。


那么如果不使用 cast,我们怎么对类型进行转换呢?


一个基本的原则就是在构建集合的时候提前进行类型转换,而不是在构建集合之后再进行整体的 cast。


比如下面的例子从一个 dynamic 类型的 List 转换成为 int 类型的 List,那么我们可以在调用 List.from 方法的时候进行类型转换:


var stuff = <dynamic>[1, 2];var ints = List<int>.from(stuff);
复制代码


如果是 map 的话,可以这样操作:


var stuff = <dynamic>[1, 2];var reciprocals = stuff.map<double>((n) => 1 / n);
复制代码


比如我们需要构建一个 int 的 List,那么在创建之初就可以指定 List 的内部类型,然后再对其添加元素:


List<int> singletonList(int value) {  var list = <int>[];  list.add(value);  return list;}
复制代码

总结

以上就是 dart 中的集合使用最佳实践。


本文已收录于 http://www.flydean.com/30-dart-collection/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 刚刚阅读数: 4
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
dart系列之:集合使用最佳实践