Типы данных К и T в ассоциативном массиве QMap могут быть базовыми типами (например, int и double), указатели и классы, которые имеют стандартный конструктор, конструктор копирования и оператор присваивания. Кроме того, тип К должен обеспечивать оператор operator < (), поскольку QMap применяет его для хранения элементов в порядке возрастания значений ключей.

Класс QMap имеет две удобные функции, keys() и values(), которые особенно полезны при работе с небольшими наборами данных. Они возвращают списки типа QList ключей и значений ассоциативного массива.

Обычно ассоциативные массивы имеют одно значение для каждого ключа: если новое значение присваивается существующему ключу, старое значение заменяется новым, чтобы не было элементов с одинаковыми ключами. Можно иметь несколько пар ключ—значение с одинаковым ключом, если использовать функцию insertMulti() или удобный подкласс QMultiMap. QMap имеет перегруженную функцию values(const К &), которая возвращает список QList со всеми значениями заданного ключа. Например:

QMultiMap multiMap;

multiMap.insert(1, "one"); multiMap.insert(1, "eins");

multiMap.insert(1, "uno");

QList vals = multiMap.values(1);

QHash — это структура данных, которая хранит пары ключ—значение в хэш—таблице. Ее интерфейс почти совпадает с интерфейсом QMap, однако здесь предъявляются другие требования к шаблонному типу К и операции поиска обычно выполняются значительно быстрее, чем в QMap. Еще одним отличием является неупорядоченность значений в QHash.

Кроме стандартных требований, которым должен удовлетворять любой тип значений, хранимых в контейнере, для типа К в QHash должен быть предусмотрен оператор operator == () и должна быть обеспечена глобальная функция qHash(), возвращающая хэш—код для ключа. Qt уже имеет перегрузки функции qHash() для целых типов, указателей, QChar, QString и QByteArray.

QHash автоматически выделяет некий первичный объем памяти для своей внутренней хэш—таблицы и изменяет его, когда элементы вставляются или удаляются. Кроме того, можно обеспечить более тонкое управление производительностью с помощью функции reserve(), которая устанавливает ожидаемое количество элементов в хэш—таблице, и функции squeeze(), которая сжимает хэш—таблицу, учитывая текущее количество элементов. Обычно действуют так: вызывают reserve(), обеспечивая максимальное ожидаемое количество элементов, затем добавляют данные и, наконец, вызывают squeeze() для сведения к минимуму расхода памяти, если элементов оказалось меньше, чем ожидалось.

Хэш-таблицы обычно имеют одно значение на каждый ключ, однако одному ключу можно присвоить несколько значений, используя функцию insertMulti() или удобный подкласс QMultiHash.

Кроме QHash в Qt имеется также класс QCache, который может использоваться для создания кэша объектов, связанных с ключом, и контейнер QSet, который хранит только ключи. Оба класса реализуются на основе QHash и предъявляют к типу К такие же требования, как и QHash.

Для прохода по всем парам ключ—значение, находящимся в ассоциативном контейнере, проще всего использовать итератор в стиле Java. Поскольку итераторы должны обеспечивать доступ и к ключу, и к значению, итераторы в стиле Java работают с ассоциативными контейнерами немного иначе, чем с последовательными контейнерами. Основное отличие проявляется в том, что функции next() и previous() возвращают пару ключ—значение, а не просто одно значение. Компоненты ключа и значения можно извлечь из объекта пары с помощью функций key() и value(). Например:

QMap map;

int sum = 0;

QMapIterator i(map);

while (i.hasNext())

sum += i.next().value();

Если требуется получить доступ как к ключу, так и к значению, мы можем просто игнорировать значение, возвращаемое функциями next() и previous(), и использовать функции итератора key() и value(), которые работают с последним пройденным элементом.

QMapIterator i(map);

while (i.hasNext()) {

i.next();

if (i.value() > largestValue) {

largestKey = i.key();

largestValue = i.value();

}

}

Допускающие запись итераторы имеют функцию setValue(), которая модифицирует значение, содержащееся в текущем элементе:

QMutableMapIterator i(map);

while (i.hasNext()) {

i.next();

if (i.value()< 0.0)

i.setValue(-i.value());

}

Перейти на страницу:

Похожие книги