Template map

  !   Данная информация предназначена только только для IT-специалистов по системной интеграции модулей БИОСОФТ-М. (см. Руководства пользователя к программным продуктам)

Контейнер map<> это гибрид hash-table + bidirectional linked list. 

Ключами могут быть любые простые скалярные типы для которых определена специализация вычислителя хеша UniversalHashKey<>. Как правило это текстовые строки, key, type<> или широко разбросанные целые числа.

Все ключи уникальны в рамках одного map<>.

Значениями, висящими на ключах, могут быть любые типы данных для которых опредлены эффективные и однозначные операторы присваивания не имеющие побочных эффектов.

Когда применять
Только инкапсулировано!

Как array. Иногда может применяться вместе с array как индекс для ускорения выборки. Всегда private. При передаче через return и параметры происходит присваивание с полным медленным копированием содержимого. Обойти это нельзя, как и с array, специально чтобы отбить желание делать неинкапсулированные хаки.

Для оптимизации скорости выборки по ключу

Применяется для осмысленной оптимизации при практически наблюдаемой по факту неэффективности поиска в array<> перебором его элементов.

Нужно понимать, что существенные накладные расходы на поддержания списков и хеш таблиц для маленького количества элементов будут только хуже чем применение array и Find.

Перед применением для оптимизации изучить реализацию хеш таблицы, ее эффективного предаллокирования и учесть расходы времени на поддержание списков по сравнению с тривиальным array<>. Проверить профайлером быстродействие на правките и для больших объемов данных сверить изменения в расходе памяти по сравнению с разумно предаллокированным array.

Учесть возможные проблемы с итераторами если публикуется метод Iterate и есть возможность удаления ключей из мапа.

Для упрощения кода

Небольшие маппинги из которых никогда ничего не удаляется (в т.ч. константные) могут быть полезны и безвредны там где быстродествие не нужно. Не забывать что map<> не экспозабелен автоматической экспозицией и для постоянного хранения более пригодны array и Udb.

Добавление элементов
    VALUE& operator [] (const KEY& key);
    map& operator << (const KEY& k);

Запись mapXxx[key] = value не может завершится отказом (пока достаточно памяти) ни при каком значении key (в отличие от array).

Запись mapXxx << key1 << key2 << ... оставляет все value в соответствующих null() значениях. Если map<> требуется только для хранения ключей, то для значений следует объявить тип unused (map<str, unused>)

Удаление элементов
    // Delete a mapping, return true if was found
    bool RemoveAtKey(
            const KEY& key);
 
    // Delete items, free hashtable, preserve reusable blocks
    void RemoveAll();
 
    // Remove only first or last mapped value
    void RemoveHead();
    void RemoveTail();

Удаление конфликтует с итераторами. Изучить Безопасный итератор для map и приватность POS указателей. Рекомендуется избегать map<> там где требуется и удаление элементов и публичные итераторы.

Получение содержимого
    // Size
    int GetCount()
            const;
 
    // Check key presence
    bool IsIn(
            const KEY& key)
            const;
 
    // Get value if mapped
    bool LookupExisting(
            const KEY& key,
            out VALUE& rValue)
            const;
 
    // With default return
    VALUE GetValueOr(
            const KEY& key,
            const VALUE& def)
            const;
 
    // nullable<> pointer support
    nullable<VALUE> LookupOrNull(
            const KEY& key)
            const;
 
    // Relative Lookup by Key
    VALUE GetValueNextToKeyOr(
            const KEY& key,
            const VALUE& def)
            const;
    VALUE GetValuePrevToKeyOr(
            const KEY& key,
            const VALUE& def)
            const;
    VALUE GetValueNextOrPrevToKeyOr(
            EMapNextPrev dir,
            const KEY& key,
            const VALUE& def)
            const;
Итераторы

Итерация всегда происходит гарантированно в последовательности добавления элементов. Это в отличие от hashmaps/dictionaries/etc в дефективных популярных системах, где порядок перебора "non-deterministic" и приложения традиционно сталкиваются с абсурдным, бугным-по-определению итератором по хешам.

    bool Iterate(
            out iter& out_i,
            out VALUE& out_value)
            const;
    bool IterateBackwards(
            out iter& out_i,
            out VALUE& out_value)
            const;
 
    bool IterateKeys(
            out iter& out_i,
            out KEY& out_key,
            out VALUE& out_value)
            const;
    bool IterateKeysBackwards(
            out iter& out_i,
            out KEY& out_key,
            out VALUE& out_value)
            const;

При удалении элементов итератор нужно прервать. Изучить Безопасный итератор для map и приватность POS указателей.

Изменение последовательности

В новых проектах пока не требовалась. Старая опасная функция с POS закрыта. Возможна реализация на ее основе безопасной функции перемещающей элемент по ключу.

Краевые значения
    // for values
    VALUE GetHeadValue()
            const;
    VALUE GetTailValue()
            const;
    VALUE GetHeadValueOr(
            const VALUE& def)
            const;
    VALUE GetTailValueOr(
            const VALUE& def)
            const;
 
    // for keys
    KEY GetHeadKey()
            const;
    KEY GetTailKey()
            const;
    KEY GetHeadKeyOr(
            const KEY& or_return_key)
            const;
    KEY GetTailKeyOr(
            const KEY& or_return_key)
            const;
Управление хешированием
    // Hash Table
    int GetHashTableSize()
            const;
    void RebuildHashTable(...);
 
    // Hash Statistics
    DMapHashStats GetHashStats()
            const;

Это замена автоматическому адаптивному механизму которая как правило не требуется.

Сначала изучить теорию. Потом реализацию. Хэш таблица классическая. При оптимизации размер задавать немного больший чем предполагаемое количество элементов, использовать prime number который ни на что не делится.

Я реализовал автоматическое адаптивное переаллокирование хеш таблицы при росте числа элементов. Оно происходит с упреждением, по тестам достаточно быстро так что на практике в ручную управлять динамическим переаллокированием пока не требовалось.

B-tree не поддерживается. Для этого есть Udb.

Экспорт
Экспозиция

Только для частного случая:

    // Assuming KEY is str and the VALUE is ref<>
    void ExposeMapStrToRef(
            ref_arg<CExpose> rExpose,
            str sKey);

map<> сейчас может декларироваться только как не экспозабельный.

В array

Ряд функций разрабатываются для эффективного превращения ключей и значений в форме array<>.

Эта категория в данный момент пуста.