简介

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.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/

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

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

dart系列之:集合使用最佳实践的更多相关文章

  1. OPEN(SAP) UI5 学习入门系列之二: 最佳实践练习(上)

    这篇博文难产了很久,原来是打算一周更新一篇的,上周原计划写MVC,但是写了一半,发现带入了太多的细节,不太符合这个入门系列的主题. 当我们学习一个新的技能的时候,如果一开始就面对大量的细节,很容易陷入 ...

  2. 【SpringMVC】SpringMVC系列15之SpringMVC最佳实践

    15.SpringMVC最佳实践 15.1.遵循Restful API最佳实践 参考:http://segmentfault.com/a/1190000002949234 15.2.统一返回字段 15 ...

  3. SpringBoot系列: Spring项目异常处理最佳实践

    ===================================自定义异常类===================================稍具规模的项目, 一般都要自定义一组异常类, 这 ...

  4. OPEN(SAP) UI5 学习入门系列之二: 最佳实践练习(下)

    上期我们完成了一个简单的主从页面,但是页面是静态的,不能交互,功能也很简单,只有一个销售订单的列表. 我们今天就一鼓作气把代码全都写完,由于本次的代码量较大,所以只对重点代码部分进行讲解. 具体每个文 ...

  5. dart系列之:和null说再见,null使用最佳实践

    目录 简介 不需要初始化对象为null null的三元操作符 如果在使用中需要判断类型是否为空,则不要使用late 本地变量的类型提升 总结 简介 null可能是大家在编写程序中最为头疼的一个东西,稍 ...

  6. dart系列之:dart语言中的变量

    目录 简介 dart中的变量 定义变量 变量的默认值 Late变量 常量 总结 简介 flutter是google在2015年dart开发者峰会上推出的一种开源的移动UI构建框架,使用flutter可 ...

  7. JSP 最佳实践: 用 jsp:include 控制动态内容

    在新的 JSP 最佳实践系列的前一篇文章中,您了解了如何使用 JSP include 伪指令将诸如页眉.页脚和导航组件之类的静态内容包含到 Web 页面中.和服务器端包含一样,JSP include  ...

  8. dart系列之:手写Library,Library编写最佳实践

    目录 简介 使用part和part of src中的文件 package中的lib文件 总结 简介 Library是dart用来组织代码的一种非常有用的方式,通过定义不同的Library,可以将非常有 ...

  9. RxJava系列7(最佳实践)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

随机推荐

  1. springboot启动过程中常用的回调

    1.介绍 springboot提供非常丰富回调接口,利用这些接口可以做非常多的事情,对于一些常用的回调接口进行介绍 2.常用的拓展接口 1.ApplicationContextInitializer ...

  2. 使用Kubernetes两年来的7大经验教训

    来源:分布式实验室译者:冯旭松在Ridecell公司管理基础设施团队几年后,我想在停下来休息时记录一些想法和经验教训. 1Kubernetes不仅仅是炒作 我在Kubernetes领域里活跃了很久,所 ...

  3. PkavHTTPFuzzer爆破带验证码的后台密码

    之前对暴力破解这块并没有做系统的总结,况且登录这块也是个重头戏,所以我想总结总结. 环境准备 1.用phpstudy搭建phpwms1.1.2演示环境 2.pkavhttpfuzzer工具 漏洞复现 ...

  4. 《剑指offer》面试题13. 机器人的运动范围

    问题描述 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上.下移动一格(不能移动到方格外),也不能进入 ...

  5. leetcode 120. 三角形最小路径和 及 53. 最大子序和

    三角形最小路径和 问题描述 给定一个三角形,找出自顶向下的最小路径和.每一步只能移动到下一行中相邻的结点上. 例如,给定三角形: [ [2], [3,4], [6,5,7], [4,1,8,3] ] ...

  6. 【C++】类-派生和继承

    类-派生和继承 目录 类-派生和继承 1.基本概念 2. 语法 3. 继承方式 4. 类型转换 5. 派生类的构造.析构函数 构造函数 复制构造函数 析构函数 1.基本概念 继承:保持已有类的特性而构 ...

  7. 【记录一个问题】thanos receiver在更换tsdb文件后,内存并未显著下降

    在16:14,切换了TSDB 在16::15分切换了TSDB,并且上游未写入数据 容器的内存并未在这个时刻明显下降 疑惑: 如果thanos receiver的内存占用不与time series数量正 ...

  8. 【记录一个问题】opencl enqueueWriteBuffer()中,cl_bool blocking参数设置无效

    err = queue.enqueueWriteBuffer(in_buf, true, 0, bmp_size, bmp_data, NULL, &event); 以上代码中,第二个参数设置 ...

  9. Redis的过期删除策略(和内存淘汰机制)-转

    版权声明:本文为CSDN博主「奥修诺斯」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明.原文链接:https://blog.csdn.net/qq_39944869/ ...

  10. mysql自连接?

    一.自连接 /* 自己查询自己 把一张表看成是两张表. 表的设计. */ SELECT * from depart; -- 具体的查询方法,查询 name ,并给添加别名. select d1.nam ...