Map(映射)

Map中的成员以“键值对”(key-value pair)的形式存在,Map也就是“键值对”的集合。同一个Map中 中的key不会重复,但不同的key可以关联到同一个value;通过key可以快速找到对应的value。理论上,Map的读写操作(查找、插入、删除)的平均时间复杂度都是O(1),即Map可以在一个常量时间内完成某个读或写操作,这个时间几乎不受Map内成员个数的影响。

flowchart TB
  subgraph abc [Map]
    subgraph ... 
    direction LR
    G(k...) --> H(v...)
    end

    subgraph entry2
    direction LR
    C(key2) --> D(value2)
    end
   
    subgraph entry1 
    direction LR
    A(key1) --> B(value1) 
    end
  end

key与value的数据类型乃参数化类型(泛型)。

abstract interface class Map<K, V> { 
  // ...
}

在稍后的示例ex651.dart中,变量 capitals的数据类型是Map<String, String>(key与value的类型均为String)。

示例

// ex651.dart
void main() {
  var capitals = {'US': 'Washington', 'UK': 'London', 'France': 'Paris'};
  print(capitals.runtimeType); // Output: _Map<String, String>

  print(capitals.entries); // 1
  // Outut: (MapEntry(US: Washington), MapEntry(UK: London), MapEntry(France: Paris))

  print(capitals.keys); // 1a Output: (US, UK, France)
  print(capitals.values); // 1b Output: (Washington, London, Paris)

  print(capitals['US']); // 2 Output: Washington
  print(capitals['Germany']); // 2a Output: null

  capitals['Germany'] = 'Berlin'; // 3
  capitals.putIfAbsent('Italy', () => 'Rome'); // 4
  print('${capitals['Germany']} ${capitals['Italy']}'); // Output: Berlin Rome

  var numbers = {'0xa': 10, '10': 10};
  print(numbers.values); // Output: 5 (10, 10)
  print(numbers.values.toSet()); // 5a Output: {10}
}
  1. 集合概述一节中已经提到,一个Map有3个Iterable对象(getter),即entries,keys 以及 values
  2. 类似于通过下标(从0开始的整数)获取List(数组)的成员,通过key来获取Map中与key对应的value(获取失败将返回null),这里的获取操作本即[]操作符方法;
  3. 与List类似,可通过[]=操作符方法,更新与key对应的value(若key不存在,则插入对应的key-value pair);
  4. putIfAbsent只有当key不存在时才更新对应的value;
  5. 请注意,values返回的是Iterable对象,不会自动去重,可通过values.toSet()获取values对应的Set。

构造函数

简单介绍一下的Map工厂构造函数:

  • Map() 创建一个空的 LinkedHashMap.
  • Map.from(Map other) 使用与other同样的 keys 与 values 创建一个 LinkedHashMap .
  • Map.fromEntries(Iterable<MapEntry<K, V>> entries) 从 entries 创建Map.
  • Map.fromIterable(Iterable iterable, {K key(dynamic element)?, V value(dynamic element)?}) 从一个Iterable对象创建Map,等价于<K, V>{for (var v in iterable) key(v): value(v)} .
  • Map.fromIterables(Iterable<K> keys, Iterable<V> values) 从给定的 keys 和 values 创建Map.
  • Map.identity() 创建一个 identity Map, 该Map使用identical(Object?, Object?)函数对key进行相等性测试.
  • Map.of(Map<K, V> other)other 创建一个LinkedHashMap
  • Map.unmodifiable(Map other)other 创建一个不可变Map.

练习

创建一个类型为Map<String,int>的Map,并准备100万(key-value pair)的测试数据,然后将测试数据逐个写入Map;在Map的长度由1万增长至100万的过程中,记录每插入100个pair的耗时;最后观察并分析这些耗时。