Подтвердить что ты не робот

Карта с двумерным ключом в java

Я хочу, чтобы карта была проиндексирована двумя ключами (карта, в которую вы помещаете И извлекаете значения, используя два ключа) в Java. Чтобы быть ясным, я ищу следующее поведение:

map.put(key1, key2, value); 
map.get(key1, key2); // returns value
map.get(key2, key1); // returns null
map.get(key1, key1); // returns null

Какой лучший способ? В частности, следует ли использовать:

  • Map<K1,Map<K2,V>>

  • Map<Pair<K1,K2>, V>

  • Другое?

(где K1, K2, V - типы первого ключа, второго ключа и значения соответственно)

4b9b3361

Ответ 1

Вы должны использовать Map<Pair<K1,K2>, V>

  • Он будет содержать только одну карту, вместо N + 1 отображений

  • Конструкция ключа будет очевидным (создание Пара)

  • Никто не запутается в отношении значение Карты как ее API-интерфейс с программным обеспечением не изменится.

  • Время ожидания в структуре данных будет короче, что хорошо, если вы обнаружите, что вам нужно синхронизировать его позже.

Ответ 2

Если вы готовы принести новую библиотеку (которую я рекомендую), посмотрите Table в Guava. Это в основном делает именно то, что вы ищете, а также, возможно, добавляете некоторые функции, где вам могут понадобиться все записи, соответствующие одному из двух ваших ключей.

interface Table<R,C,V>

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

Ответ 3

Я бы рекомендовал второй вариант

Map<Pair<K1,K2>,V>

Первый из них будет генерировать больше перегрузки при извлечении данных и даже больше при вставке/удалении данных с карты. Каждый раз, когда вы добавляете новое значение V, вам нужно проверить, существует ли карта для K1, если не создать ее, и поместить ее в основную карту, а затем поместить значение с помощью K2.

Если вы хотите иметь интерфейс, который вы выставляете, сначала оберните свой Map<Pair<K1,K2>,V> своим собственным "DoubleKeyMap".

(И не забудьте правильно реализовать методы hash и equals в классе Pair!!)

Ответ 4

Я бы выбрал решение Map<Pair<K1,K2>, V>, потому что:

  • он прямо выражает то, что вы хотите сделать
  • является потенциально более быстрым, поскольку он использует меньше ограничений
  • упрощает код клиента (код, который использует Map впоследствии

Ответ 5

Логично, что вы Pair (key1, key2) соответствуют чему-то, так как это ключ вашей карты. Поэтому вы можете написать свой собственный класс с K1 и K2 в качестве параметров и переопределить метод hashCode() (плюс, возможно, другие методы для большего удобства). Это явно кажется "чистым" способом решения вашей проблемы.

Ответ 6

Пока я также нахожусь на борту того, что вы предложили (пара значений для использования в качестве ключа), вы также можете рассмотреть возможность создания оболочки, которая может удерживать/сопоставлять оба ключа. Это может несколько запутать вас, поскольку вам нужно будет переопределить методы equals и hashCode и выполнить эту работу, но это может быть простой способ указать следующему человеку, использующему ваш код, что ключ должен быть особого типа.

Поиск немного, я нашел этот пост, который может вам пригодиться. В частности, из коллекции Apache Commons, MultiKeyMap. Я никогда не использовал это раньше, но это похоже на достойное решение и, возможно, стоит изучить.

Ответ 7

Я использовал массив для ключа: вроде этого

Map<Array[K1,K2], V>