Коротко о различиях между несколькими Картами в дартс

Flutter
  • Эта статья была разрешена для публикации в публичном аккаунте OpenFlutter.

Все версии, просьба указывать при перепечаткепроисхождение.

Dart имеет несколько встроенных коллекций, таких какSet,Listтак же какMap. Знание сильных и слабых сторон их реализации может помочь вам их использовать.

Эта статья демонстрируется в Dart 2.1.1. Если есть какие-либо ошибки, пожалуйста, поправьте меня.

Что такое карта

Карта — это ассоциативный контейнер, который сопоставляет ключи со значениями. Ключи уникальны и могут указывать на одно и только одно значение, но значения могут повторяться. ключ не может бытьnull, но значение может бытьnull.

Литерал карты

Дарт это поддержкаЛитерал карты, поэтому вы можете создать объект Map следующим образом:

var gifts = {
  // Key:    Value
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};

В спецификации упоминается, что литералы карты должны сохранять порядок вставки. это означаетgiftsдаLinkedHashMapпример. Давайте проверим:

   print("type of gifts:${gifts.runtimeType}");
   //type of gifts:_InternalLinkedHashMap<String, String>

new Map()

Dart поддерживает фабричные конструкторы, поэтому мы также можем создать карту следующим образом:

var gifts= new Map();

Начиная с Dart2, новый необязателен. Не упоминай об этом снова.

ОднакоMapЭто абстрактный класс, что означает, что приведенный выше код на самом деле является экземпляром, созданным подклассом Map. ТакgiftsКакой именно тип? Аналогично, напечатаем:

   print("type of gifts:${gifts.runtimeType}");
  // type of gifts:_InternalLinkedHashMap<dynamic, dynamic>

Фактически, в более ранних версиях Dartnew Map()фактически создаетHashMap. но, Dart bug 5803упоминается для того, чтобы сделать{}а такжеnew Map()возвращает тот же тип,new Mapскоро вернетсяLinkedHashMapпример.

LinkedHashMap

LinkedHashMapупорядочен, он повторяет ключи в порядке вставки:

 var ordered = new LinkedHashMap();
   ordered['32352'] = 'Alice';
   ordered['95594'] = 'Bob';

   for (var key in ordered.keys) {
     print(key);
   }

    // 一定是先打印 32352, 然后打印95594

Изменение значения ключа не меняет порядок вставки ключей, но удаление, а затем добавление изменит порядок вставки:

 var ordered = new LinkedHashMap();
   ordered['32352'] = 'Alice';
   ordered['95594'] = 'Bob';
   ordered['45684'] = 'Kal';

   for (var key in ordered.keys) {
     print("仅遍历:$key");
   }

   ordered['95594'] = 'James';
   for (var key in ordered.keys) {
     print("改变一个值:$key");
   }
   
   ordered.remove('95594');
   ordered['95594'] = 'Kobe';
   for (var key in ordered.keys) {
     print("改变一个值:$key");
   }

Результат выглядит следующим образом:

 仅遍历:32352
 仅遍历:95594
 仅遍历:45684
 改变一个值:32352
 改变一个值:95594
 改变一个值:45684
 删除后再添加:32352
 删除后再添加:45684
 删除后再添加:95594

HashMap

HashMapПорядок вставки данных не гарантируется. при пересеченииHashMap, порядок пар ключ-значение не гарантируется. можно создать следующим образомHashMap:

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

Используйте, когда вас не волнует порядок пар ключ-значениеHashMap.  Исходный код HashMap находится здесь.

SplayTreeMap

Splay tree (разделенное дерево) — это самобалансирующееся бинарное дерево поиска с быстрым доступом к последним посещенным элементам. Он может выполнять операции вставки, поиска и удаления за O(log n).

import 'dart:collection';
main() {
  var gifts= new SplayTreeMap();
}

SplayTreeMap требует, чтобы все ключи были одного типа:

   var splayTreeMap = SplayTreeMap();
   splayTreeMap["1"] = "s";
   splayTreeMap[1] = "2";

Приведенный выше синтаксис кода хорош, но не разрешен во время выполнения:

type 'int' is not a subtype of type 'String' of 'other'

Для часто хранимых и доступных данных (таких как кеши),SplayTreeMapхороший выбор. Причина в том, что они используют вращение дерева, чтобы привести элемент к корню для более частых посещений. Производительность исходит из самооптимизации дерева. То есть часто используемые элементы перемещаются ближе к верху. Однако, если к дереву часто обращаются одновременно, используйтеSplayTreeMapпочти бессмысленно.

Например, модем-маршрутизатор получает сетевые пакеты с очень высокой скоростью. Модем должен решить, какой пакет идет по какой линии. Этого можно добиться с помощью карты, где ключом является IP-адрес, а значением — линия назначения. В этом случае,SplayTreeMap— хороший выбор, так как большинство IP-адресов будут использоваться несколько раз, поэтому их можно найти в корне дерева.

заключительные замечания

В этой статье кратко объясняются различия между несколькими картами в Dart.Хотя она не объясняет конкретную реализацию, я надеюсь, что она может быть полезной. Наша группа связи QQ: 892398530.