Карта с двумерным ключом в 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 - типы первого ключа, второго ключа и значения соответственно)
Ответы
Ответ 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>