Коллекция пар ключ-значение с сохранением порядка и извлечением по ключу и по индексу пары?

Я хотел бы использовать набор пар "ключ-значение":

  • Это основа для данных JTable модель (реализация TableModel), поэтому мне нужно получить доступ к элементам по их индексу / позиции (например, для реализации Object getValueAt(int rowIndex, int columnIndex)). Коллекция должна сохранять порядок элементов. Для этого подойдет ArrayList.
  • Что позволяет извлекать элементы по значению ключа. Для этого подойдет HashMap.

Самая близкая к использованию коллекция, которую я нашел, - это LinkedHashMap . Он сохраняет порядок и позволяет выполнять поиск по ключу. Однако доступ к элементу по индексу / позиции невозможен, я должен перебирать элементы, пока не будет найден подходящий. Это неэффективно по времени.

Есть ли лучший вариант, чем этот ? Спасибо.


(Вопрос похож на этот, но в предложенном решении используется преобразование toArray(), которое не является эффективным по времени. Если набор пар изменится, преобразование необходимо выполнить снова.)


person mins    schedule 08.09.2014    source источник
comment
попробуйте SortedMap() || TreeMap() .. или создайте для него собственный класс.   -  person user3145373 ツ    schedule 08.09.2014


Ответы (3)


В JRE нет такой реализации коллекции.

Но вы можете легко решить эту проблему, используя Map<K,V> для хранения пар ключ-значение и дополнительный List<K> для хранения ключей в последовательном порядке. Затем вы можете получить доступ к значению либо по ключу, либо по индексу, используя: keyValueMap.get(keys.get(index)).

Вы должны убедиться, что модификации всегда синхронизируются в обеих коллекциях:

  • Добавить / изменить запись: if (keyValueMap.put(key, value) == null) keys.add(key)
  • Удалить запись: if (keyValueMap.remove(key) != null) keys.remove(key)

Обратите внимание, что эта реализация предполагает, что значения никогда не равны null. Если также требуются значения null, код становится немного сложнее, поскольку нам нужно проверять наличие записи с помощью keyValueMap.contains(key).

person isnot2bad    schedule 08.09.2014
comment
Легко и приятно. Спасибо. Следует знать, что Map :: put (k, v) также возвращает null при обновлении предыдущей записи, где v было null, для реализаций, допускающих null. - person mins; 08.09.2014
comment
@mins вы правы, нулевые значения здесь не поддерживаются. Я добавил примечание к своему ответу, чтобы решить эту проблему. - person isnot2bad; 09.09.2014

Без реализации вашей собственной коллекции может быть проще всего иметь две коллекции с перевернутым ключом-значением во второй, но в остальном упорядоченным так же.

(хотел, чтобы это был комментарий, но пока недостаточно репутации)

person Eben    schedule 08.09.2014

Коллекция Apache Commons имеет ListOrderedMap, который сделает то, что вы хотите.

person Pino    schedule 08.09.2014
comment
Оценил, полезно знать. Спасибо. Возможно, решение заключается в использовании других классов из пакета. Для использования только этого я предпочитаю использовать std API. - person mins; 08.09.2014