Карта с несколькими ключами на одно значение Java - PullRequest
18 голосов
/ 21 июля 2011

Я думаю, что мой вопрос похож на этот: Как реализовать карту с несколькими ключами? , но с важным отличием.В этом вопросе (если мое понимание этого правильное, пожалуйста, дайте мне знать, если это не так), ключи должны были всегда быть уникальными.Я хочу иметь карту в виде: MyMap , где ключи не обязательно уникальны.Если это не имеет смысла, я в основном хочу двумерный массив, но вместо того, чтобы ссылаться на элементы по координатам, я хочу ссылаться на них по парам объектов.библиотека, где это работает или хороший способ реализовать это сам?Что касается библиотек, я смотрел на Apache Commons и Guava, и, похоже, у меня нет того, что я хочу.

Ответы [ 4 ]

18 голосов
/ 21 июля 2011

Структура данных Table в Гуаве, кажется, удовлетворяет вашему требованию ссылки на значение парой объектов.

13 голосов
/ 21 июля 2011

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

В любом случае, вы упомянули, что хотите получить доступ к элементам, используя пару объектов. Вы можете создать класс, который будет содержать ключи, такие как

public class Pair {
  // string represntation of an object
  private final String x; 
  private final String y;

  // ctor, getters...

  public int hashcode() {...}
  public boolean equals(Object other) {...}
}

Метод hashcode сгенерирует хеш-код для всех составляющих элементов (в данном случае два, x и y в вашем случае, но может быть легко расширен для поддержки произвольного числа элементов) и два ключи будут одинаковыми, если они имеют одинаковые значения для x и y. Если ваши элементы пары не являются простыми строками, тривиально получить строковое представление практически любого объекта (например, обеспечить достойную реализацию метода toString).

Идея состоит в том, чтобы иметь уникальное строковое представление для каждого элемента в паре.

Конечно, генерация твердых хеш-кодов не тривиальна, поэтому отличный вариант - использовать Strings. Чтобы сгенерировать хеш-код, вы просто добавили бы строковые представления ваших парных объектов:

public int hashcode() {
  return ('x' + x + ":y" + y).hashcode();
}

Обязательно укажите какой-нибудь разделитель. В противном случае для таких значений, как x=ab, y=b и x=a, y=bb, вы получите один и тот же хэш-код, даже если объекты совершенно разные.

И равенство так же тривиально, как проверка значения элементов в паре:

public boolean equals(Object other) {
  // if other is not null and is an instance of Pair
  final Pair otherPair = (Pair)other;
  return this.x.equals(otherPair.x) && this.y.equals(otherPair.y);
}

Итак, теперь вы можете использовать свой класс Pair на карте, например:

final Map<Pair, Whatever> map = new Hashmap<Pair, Whatever>();
// ...

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

Если вы хотите использовать свой класс Pair в TreeMap, вам придется реализовать метод compareTo или предоставить собственный Comparator при создании такой карты. Реализации TreeMap полагаются на результат метода compareTo, чтобы определить, где должно быть назначено значение.

3 голосов
/ 06 ноября 2017

Коллекции Apache Commons имеют MultiKey .

import org.apache.commons.collections4.keyvalue.MultiKey;

Map<MultiKey, ValueType> myMap = new HashMap<MultiKey, ValueType>();
myMap.put(new MultiKey(key1, key2), value);

myMap.get(new MultiKey(key1, key2));

Преимущество состоит в создании N-мерных массивов из карты.

2 голосов
/ 21 июля 2011

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

Как вы можете его инициализировать:

    HashMap<Key1, HashMap<Key2, Value>> nestedHashMap = new HashMap<Key1, HashMap<Key2, Value>>();

Добавление значений:

    Key1 first;
    Key2 second;
    Value data;
    HashMap<Key2, Value> tempMap = new HashMap<Key2, Value>();
    tempMap.put(second, data);
    nestedHashMap.put(first, tempMap);

Получение данных обратно:

    Key1 first;
    Key2 second;
    Value data;
    data = nestedHashMap.get(first).get(second);

Отказ от ответственности: Этот код не был проверен, он просто выпал из моей головы.

...