Карта Java на основе ссылки на объект?

#java

#java

Вопрос:

Итак, я хотел бы использовать карту Java, где ключи являются объектом…но вместо того, чтобы вводить значение объекта, они вводят идентификатор объекта. Итак, что-то вроде следующего было бы полностью допустимым кодом:

 Map<String, Integer> map = new HashMap<String, Integer>();

String s1 = "hi!";
String s2 = "hi!";

map.put(s1, 10);
map.put(s2, 47);
  

Возможно ли это? Есть ли простой способ сделать это без создания идентификатора объекта или чего-то чрезмерно громоздкого в моем классе? В принципе, мне нужен способ связать постоянно меняющийся список значений с данным объектом. Этот список значений потенциально будет отличаться для объектов, имеющих одинаковое значение, следовательно, карта по умолчанию не работает. Кроме рефакторинга моего класса, чтобы сделать это самому (на самом деле это не вариант, учитывая время), есть ли что-нибудь, что я мог бы использовать?

Спасибо.

РЕДАКТИРОВАТЬ: Дополнительная информация.

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

Комментарии:

1. Если вы не реализуете equals() и hashCode() самостоятельно, вы в основном наследуете Object реализацию s, которые сравниваются по идентификатору, а не по равенству.

2. @Helper: Я думаю (не уверен), что строка переопределяет equals() и hashCode() так, чтобы она сравнивалась по равенству. В противном случае ни одна из моих карт на основе строк не работала бы: (

3.@Giacomo: String абсолютно переопределяет equals() и hashCode() .

4. Правильно, но он говорит in my class . Насколько я понимаю, String s были приведены только в качестве примеров.

Ответ №1:

Я думаю, IdentityHashMap сделает свое дело. Однако обе строки будут указывать на один и тот же экземпляр, поскольку вы использовали строковый литерал. Попробуйте s1 = новая строка («привет!») и s2 = новая строка («привет!») вместе с IdentityHashMap вместо этого.

Комментарии:

1. Не думал об этом. 1 Но, возможно, запрашивающий ищет мультикарту, и он не формализует ее правильным образом. Я нахожу, что дизайн (s1 и s2 по существу равны, но указывают на разные значения) не очень хорош.

Ответ №2:

Вам следует взглянуть на IdentityHashMap.

Этот класс реализует интерфейс карты с хэш-таблицей, используя равенство ссылок вместо равенства объектов при сравнении ключей (и значений).

Комментарии:

1. Это точно правильный ответ. Поскольку для этого не требуется дополнительная зависимость, такая как Guava

Ответ №3:

Ознакомьтесь с мультикартами от Guava (реализации перечислены на Multimap странице интерфейса).

Комментарии:

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

2. В моем примере я должен был быть более понятным, но рассматриваемый объект не является строкой. Хотя возможно, что дизайн мог бы быть лучше, я ОПРЕДЕЛЕННО хочу связать разные значения с конкретными объектами, которые могут быть семантически идентичны.

3. Итак, если объект не является строкой и не переопределяет equals() и hashCode(), то equals() и hashCode() работают путем проверки идентичности. Итак, вам не нужно ничего другого, кроме стандартной карты. Вы переопределяете equals () и hashCode () ? Если ответ «да», вы на 100% правы.

Ответ №4:

Вы ищете мультикарту. Java Collection Framework не дает вам этого. Но вы можете имитировать это, связывая LinkedList (в конечном итоге с одним элементом) с каждым ключом. Это очень просто.

Ответ №5:

Просто для полноты: Guava ‘s MapMaker создает карты с эквивалентностью идентификаторов по умолчанию для слабых и программных клавиш. Посмотрите на код здесь