Ответ 1
Структура Table в Гуаве, по-видимому, отвечает вам требованием ссылаться на значение парой объектов.
Я думаю, что мой вопрос похож на этот: Как реализовать карту с несколькими ключами?, но с важным отличием. В этом вопросе (если мое понимание этого правильное, сообщите мне, если это не так), ключи должны были всегда быть уникальными. Я хочу иметь карту в форме: MyMap где ключи не обязательно уникальны. Если это не имеет смысла, я в основном хочу 2-мерный массив, но вместо того, чтобы ссылаться на элементы по координатам, я хочу ссылаться на них парами объектов.
У кого-нибудь есть идеи относительно библиотеки, где это работает, или хорошего способа реализовать это самостоятельно? Что касается библиотек, я смотрел Apache Commons и Guava, у меня, похоже, не было того, что я хочу.
Структура Table в Гуаве, по-видимому, отвечает вам требованием ссылаться на значение парой объектов.
Я надеюсь, что этот ответ не будет рассматриваться как раскаяние, но, насколько я понял, вы хотите использовать библиотеку для чего-то, что вы можете достичь тривиально, используя 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
).
Идея состоит в том, чтобы иметь уникальное строковое представление для каждого элемента в паре.
Конечно, создание твердых хэш-кодов не является тривиальным, поэтому отличным вариантом является использование строк. Чтобы создать хэш-код, вы просто добавите строковые представления ваших парных объектов:
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>();
// ...
В основном, hashmap работает, используя хэш-код ключей, чтобы определить, в каком ведре должно быть выделено значение. Если два ключа имеют один и тот же хэш-код, то метод equals будет использоваться для определения того, произошло ли только столкновение, или если это только тот же ключ.
Если вы хотите использовать класс Pair
в TreeMap
, вам придется реализовать метод compareTo
или предоставить свой собственный Comparator
при создании такой карты. TreeMap
реализация полагается на результат метода compareTo
, чтобы определить, где должно быть выделено значение.
Мне кажется, что вы ищете вложенный 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);
Отказ от ответственности: этот код не был протестирован, он просто сошел с моей головы.
Коллекции коллекций Apache имеют 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-мерные массивы с карты.