【发布时间】:2013-02-02 13:37:33
【问题描述】:
Dart 有一个 Map 类型,具有 HashMap、LinkedHashMap 和 SplayTreeMap 等实现。这些不同的 Map 实现有什么区别?
【问题讨论】:
标签: dart
Dart 有一个 Map 类型,具有 HashMap、LinkedHashMap 和 SplayTreeMap 等实现。这些不同的 Map 实现有什么区别?
【问题讨论】:
标签: dart
Dart 内置了对 List、Set 和 Map 等集合的支持。 Dart 有不同的 Map 实现。了解实现之间的优缺点可以帮助您做出明智的决定。
(注意:这是在 Dart M3 的时候写的,所以下面的内容可能与此刻的文档不匹配。)
Map 是一个关联容器,将键映射到值。键是唯一的,并且可以指向一个且只有一个值。键不能为空,但值可以为空。
Dart 支持Map literals,像这样:
var accounts = {'323525': 'John Smith', '588982': 'Alice Jones'};
规范说地图文字必须保持插入顺序。这意味着accounts 是LinkedHashMap 的一个实例。
规范还规定 Map 文字键必须是字符串。将来可能会改变。
Dart 支持工厂构造函数,因此您可以像这样创建新的 Map 实例:
var accounts = new Map();
Map 类是抽象的,这意味着工厂构造函数实际上创建了Map 子类的实例。那么accounts 的实际类型是什么?
较早版本的 Dart 从 new Map() 构造函数创建了一个新的 HashMap 实例。然而,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 的键或值时,您不能期望一定的顺序。
HashMap 是使用hash table 实现的。
这里是一个创建新HashMap的例子:
import 'dart:collection';
main() {
var accounts = new HashMap();
}
如果您不关心维护插入顺序,请使用 HashMap。
splay 树是一种自平衡二叉搜索树,具有最近访问的元素可以快速再次访问的附加属性。它在 O(log(n)) 摊销时间内执行插入、查找和删除等基本操作。
import 'dart:collection';
main() {
var accounts = new SplayTreeMap();
}
SplayTreeMap 要求所有键的类型相同。
对于经常存储和访问的数据(如缓存),展开树是一个不错的选择。原因是他们使用树旋转来将元素带到根,以便更频繁地访问。性能来自树的自我优化。也就是说,经常访问的元素被移到更靠近顶部的位置。但是,如果树的访问频率相同,那么使用张开树图就没有什么意义了。
一个示例是调制解调器路由器以非常高的速率接收网络数据包。调制解调器必须决定哪个数据包进入哪条线路。它可以使用映射实现,其中键是 IP,值是目的地。在这种情况下,张开树图是一个不错的选择,因为大多数 IP 地址会被多次使用,因此可以从树的根部找到这些地址。
【讨论】:
还有一个选择。
多地图
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
}
【讨论】: