Есть ли недостатки в использовании произвольных объектов в качестве ключей карты в Java?

StackOverflow https://stackoverflow.com/questions/635014

  •  10-07-2019
  •  | 
  •  

Вопрос

В моем приложении есть два типа объектов, где каждому объекту одного типа соответствует ровно один объект другого типа.

Очевидным выбором для отслеживания этих отношений является Map<type1, type2>, как HashMap.Но что-то я подозрительно.Могу ли я использовать объект в качестве ключа на Карте, передавать его, хранить в другой коллекции и в любое время извлекать его партнера из Карты?

После создания объекта я передаю только идентификатор, верно?Так что, наверное, здесь нет проблем.Что если я сериализую и десериализую ключ?

Есть еще какие-нибудь предостережения?Должен ли я использовать что-то еще для корреляции пар объектов, например число, которое я генерирую сам?

Это было полезно?

Решение

<Ол>
  • Ключ должен быть правильно реализован .equals() и .hashCode()
  • Ключ не должен быть изменен каким-либо образом, который изменяет его значение HashMap, пока он используется в качестве ключа
  • В идеале любой объект, используемый в качестве ключа в <=>, должен быть неизменным. Это автоматически гарантирует, что 2. всегда будет верным.
  • Объекты, которые в противном случае могли бы быть GCed, могут храниться, когда они используются в качестве ключа и / или значения.
  • Другие советы

      

    У меня есть два вида объектов в моем   приложение, где каждый объект одного   вид имеет ровно один соответствующий   объект другого вида.

    Это действительно звучит как отношение has-a и, следовательно, может быть реализовано с использованием простого атрибута.

    Это зависит от реализации выбранной вами карты:

    • Хэшмап использует равно() и хэш-код().По умолчанию (в Object) они основаны на идентификаторе объекта, который будет работать нормально, если вы не сериализуете/десериализуете.При правильной реализации методовquals() и hashCode() на основе содержимого объекта у вас не возникнет проблем, если вы не измените его, пока он является ключом в хэш-карте.

    • ДеревоКарта использует по сравнению с().Реализации по умолчанию не существует, поэтому вам необходимо ее предоставить.Применяются те же ограничения, что и для реализации hashCode() и equals() выше.

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

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

      

    Могу ли я использовать объект в качестве ключа на карте, передать его, поместить его в другую коллекцию и в любое время получить своего партнера с карты?

    Да, здесь вообще нет проблем.

      

    После создания объекта все, что я передаю, это идентификатор, верно? Так что, вероятно, нет проблем там. Что если я сериализую и десериализую ключ?

    Правильно, вы только передаете ссылку - все они будут указывать на один и тот же реальный объект. Если вы сериализуете или десериализуете объект, это создаст новый объект. Однако, если ваш объект правильно реализует функции equals и hashCode, вы все равно сможете использовать новый десериализованный объект для извлечения элементов с карты.

      

    Любые другие предостережения? Должен ли я использовать что-то еще для сопоставления пар объектов, например, число, которое я генерирую сам?

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

    Любой объект может быть ключом карты. Здесь важно убедиться, что вы переопределяете .equals () и .hashCode () для любых объектов, которые будут использоваться в качестве ключей карты.

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

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

    Точки сбоя - это хэш-код и функции равенства. Если они не дают последовательных и правильных возвращаемых значений, карта будет вести себя странно. Эффективная Java имеет целый раздел и настоятельно рекомендуется.

    Вы можете рассмотреть коллекцию Google. BiMap .

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top