Dart中不同Map实现之间有什么区别?

时间:2013-02-18 06:54:59

标签: dart

Dart的地图类型包含HashMapLinkedHashMapSplayTreeMap等实施。这些不同的Map实现之间有什么区别?

3 个答案:

答案 0 :(得分:40)

Dart内置了对List,Set和Map等集合的支持。 Dart有不同的Map实现。了解实施之间的利弊可以帮助您做出明智的决定。

(注意:这是在Dart M3时代写的,所以下面的内容可能与此时的文档不符。)

什么是地图?

Map是一个关联容器,将键映射到值。键是唯一的,可以指向一个且只能指向一个值。键不能为null,但值可以为null。

地图文字

Dart支持Map literals,如下所示:

var accounts = {'323525': 'John Smith', '588982': 'Alice Jones'};

规范说地图文字必须保持插入顺序。这意味着accountsLinkedHashMap的实例。

规范还说地图文字键必须是字符串。这可能会在将来发生变化。

新地图()

Dart支持工厂构造函数,因此您可以像这样创建Map的新实例:

var accounts = new Map();

Map类是抽象的,这意味着工厂构造函数实际上创建了Map的子类的实例。那么accounts的实际类型是什么?

早期版本的Dart从HashMap构造函数创建了new Map()的新实例。但是,Dart bug 5803声明为了使{}new Map返回相同的类型,new Map很快会返回LinkedHashMap的实例。

LinkedHashMap(或,InsertionOrderedMap)

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。

以下是创建新HashMap的示例:

import 'dart:collection';
main() {
  var accounts = new HashMap();
}

如果您不关心维护广告订单,请使用HashMap。

这是source code of HashMap

SplayTreeMap

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

在使用包含HashMapLinkedHashMapSplayTreeMap以及本答案其余部分中的其他代码的这些语法之前,请不要忘记导入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>. 您也可以声明MapLinkedHashMapSplayTreeMap,而无需设置其键和值的类型。这是什么意思?向地图添加<int, String>对不会限制我们。

这些地图现在接受其他类型:<String, String><String, int>

Map map = Map();
HashMap map1 = HashMap();
LinkedHashMap map2 = LinkedHashMap();
SplayTreeMap map3 = SplayTreeMap();

更多:A complete reference