Dart的地图类型包含HashMap,LinkedHashMap和SplayTreeMap等实施。这些不同的Map实现之间有什么区别?
答案 0 :(得分:40)
Dart内置了对List,Set和Map等集合的支持。 Dart有不同的Map实现。了解实施之间的利弊可以帮助您做出明智的决定。
(注意:这是在Dart M3时代写的,所以下面的内容可能与此时的文档不符。)
Map是一个关联容器,将键映射到值。键是唯一的,可以指向一个且只能指向一个值。键不能为null,但值可以为null。
Dart支持Map literals,如下所示:
var accounts = {'323525': 'John Smith', '588982': 'Alice Jones'};
规范说地图文字必须保持插入顺序。这意味着accounts
是LinkedHashMap
的实例。
规范还说地图文字键必须是字符串。这可能会在将来发生变化。
Dart支持工厂构造函数,因此您可以像这样创建Map的新实例:
var accounts = new Map();
Map
类是抽象的,这意味着工厂构造函数实际上创建了Map
的子类的实例。那么accounts
的实际类型是什么?
早期版本的Dart从HashMap
构造函数创建了new Map()
的新实例。但是,Dart bug 5803声明为了使{}
和new Map
返回相同的类型,new Map
很快会返回LinkedHashMap
的实例。
LinkedHashMap
按照插入的顺序迭代键和值。
注意: LinkedHashMap可能会重命名为InsertionOrderedMap。关注Dart bug 2349以取得进展。
以下是一个例子:
import 'dart:collection';
main() {
var ordered = new LinkedHashMap();
ordered['32352'] = 'Alice';
ordered['95594'] = 'Bob';
for (var key in ordered.keys) {
print(key);
}
// guaranteed to print 32352, then 95594
}
这是source code for LinkedHashMap。 (如果此链接停止工作,可能是因为该类已重命名)
HashMap无法保证维护广告订单。当您遍历HashMap的键或值时,您不能指望某个订单。
使用hash table实现HashMap。
以下是创建新HashMap的示例:
import 'dart:collection';
main() {
var accounts = new HashMap();
}
如果您不关心维护广告订单,请使用HashMap。
splay树是一种自平衡二进制搜索树,具有附加属性,最近访问过的元素可以再次快速访问。它在O(log(n))摊销时间内执行插入,查找和删除等基本操作。
import 'dart:collection';
main() {
var accounts = new SplayTreeMap();
}
SplayTreeMap要求所有键都属于同一类型。
对于经常存储和访问的数据(如缓存),splay树是一个不错的选择。原因是他们使用树旋转将一个元素调到根,以便更频繁地访问。性能来自树的自我优化。也就是说,频繁访问的元素移动到更靠近顶部。但是,如果同时经常访问树,那么使用splay树映射就没那么重要了。
示例案例是以非常高的速率接收网络数据包的调制解调器路由器。调制解调器必须决定哪个数据包进入哪个线路。它可以使用映射实现,其中键是IP,值是目标。对于这种情况,splay树映射是一个不错的选择,因为大多数IP地址将被多次使用,因此可以从树的根目录找到它们。
答案 1 :(得分:0)
还有一种选择。
多图
import 'package:quiver/collection.dart';
algorithms() {
var ordered = new ListMultimap();
ordered.add('32352', 'Alice');
ordered.add('95594', 'Bob');
ordered.add('32352', 'Alice2');
for (var key in ordered.keys) {
print(key);
}
for (var value in ordered.values) {
print(value);
}
// print in ascending order
// flutter: 32352
// flutter: 95594
// flutter: Alice
// flutter: Alice2
// flutter: Bob
}
答案 2 :(得分:0)
有关Dart Map的注意事项
Dart Map
是键值对的集合。它将每个键精确地映射到一个值。我们可以遍历地图。
地图有3种类型,具体取决于迭代顺序:
HashMap
是无序的。可以先订购稍后提供的键/值对。LinkedHashMap
具有插入顺序可预测的迭代顺序。稍后推出的键/值对将在以后订购。SplayTreeMap
以已排序的顺序迭代键。这是一棵自平衡的二叉树,经常访问的元素将更靠近树的根。默认情况下,使用Map
构造函数(Map()
,Map.from()
,Map.of())
创建实例将返回LinkedHashMap
。
无论我们在哪里使用Map
,您都可以考虑使用LinkedHashMap
,也可以将Map替换为LinkedHashMap
。
在Dart / Flutter中创建新地图
使用新关键字,我们可以创建一个新的Map
。
在使用包含HashMap
,LinkedHashMap
,SplayTreeMap
以及本答案其余部分中的其他代码的这些语法之前,请不要忘记导入dart:collection库。
import 'dart:collection';
main() {
HashMap hashMap = new HashMap<int, String>();
LinkedHashMap linkedHashMap = new LinkedHashMap<int, String>();
SplayTreeMap treeMap = new SplayTreeMap<int, String>();
}
在最新的Dart版本中,我们不再需要使用new
关键字。
例如,接受HashMap map = HashMap<int, String>()
。
我们可以使用LinkedHashMap
这样的构造函数来创建新的Map
。
Map map = Map<int, String>();
if (map is LinkedHashMap) {
print("This is a LinkedHashMap.");
}
// Result: This is a LinkedHashMap.
在上面的代码中,我们指定键值对的类型:<int, String>.
您也可以声明Map
,LinkedHashMap
,SplayTreeMap
,而无需设置其键和值的类型。这是什么意思?向地图添加<int, String>
对不会限制我们。
这些地图现在接受其他类型:<String, String>
,<String, int>
…
Map map = Map();
HashMap map1 = HashMap();
LinkedHashMap map2 = LinkedHashMap();
SplayTreeMap map3 = SplayTreeMap();