Использовать хеш-карту Java, даже если сопоставления нет?

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

Но из того, что я видел, хеш-карты всегда связывают значение с другим? Например, «Джон» и «555-5555», его номер телефона.

Теперь моя ситуация. Предположим, у меня есть группа людей, и каждый из них связан с другими людьми. Итак, мне нужно, чтобы каждый человек сохранял свои контакты.

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

EDIT Я не думаю, что HashSet решит мою проблему, потому что мне нужно получить значение для его обновления, а метода get нет. Remove возвращает логическое значение, поэтому я даже не могу удалить его, чтобы вернуть обратно, что, вероятно, в любом случае было бы плохой идеей.


person they changed my name    schedule 29.12.2009    source источник
comment
Похоже, что вам нужен набор, а не карта. И я бы не стал слишком зацикливаться на хешировании. На каком языке ты говоришь?   -  person    schedule 30.12.2009
comment
Какой критерий вы будете использовать для получения объекта? Этот критерий звучит как лучший хэш для использования ...   -  person Chinmay Kanchi    schedule 30.12.2009


Ответы (7)


Я не думаю, что HashSet решит мою проблему, потому что мне нужно получить значение, чтобы обновить его, а метода get нет.

Это загадочное заявление. Зачем вам извлекать значение, используя метод get для его обновления? Конечно, если вы знаете, какой объект вам нужно получить из набора / карты, вам не нужно его получать.

Например:

HashSet<Person> relations = ...
Person p = ...
if (relations.remove(p)) {
    // we removed an object such that p.equals(obj) is true.
}

Теперь, если вас беспокоит, что удаленный объект был равен, но не идентичен p, мне кажется, что с вашим дизайном что-то не так. Либо:

  • вам не следует создавать несколько Person одинаковых экземпляров, или
  • вы не должны заботиться о том, что Person экземпляры не идентичны, или
  • вы не должны были переопределять equals(Object).

Короче говоря, проблема в том, что вы неправильно управляете идентификацией объекта.

person Stephen C    schedule 30.12.2009

Если все, что вам нужно, это проверить, является ли A одним из контактов B, тогда Set - выбор. Для этого в нем есть contains ().

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

Если не существует нескольких экземпляров одного и того же человека, я бы сказал для каждого человека определить идентификатор, например уникальный атрибут, и использовать его в качестве ключа для карты контактов. Кроме того, вы определяете equal () / hashCode () для класса людей? Map / Set использует hashCode () и equal () для поиска совпадения. В зависимости от вашего использования, вам может потребоваться переписать их для повышения эффективности.

person bryantsai    schedule 30.12.2009

Что ж, структура данных, которую вы здесь ищете, будет HashSet (или каким-то другим набором), я думаю (если ваш фреймворк / библиотека это предлагает). В наборе просто написано «У меня есть следующие элементы» вместо «У меня есть следующие элементы, сопоставленные со следующими значениями». Это то, что вы здесь моделируете.

Что касается HashSet по сравнению с другими реализациями (если они есть): все зависит от того, что вы делаете. Если вам нужен быстрый поиск, т.е. е. "этот элемент в наборе?" вопросы, то хеширование - это хорошо. Другие базовые структуры данных, возможно, лучше оптимизированы для других операций с множеством, таких как объединение, пересечение и т. Д.

person Joey    schedule 29.12.2009

Хэш-таблица / карта просто требует, чтобы у вас был способ получить значения, которые вы хотите найти позже; вот для чего нужен ключ.

Однако в вашем конкретном случае это похоже на то, что вы ищете способ сохранить отношения между людьми, и вы отслеживаете, есть ли у человека A отношения с человеком B. это список смежности.

person John Feminella    schedule 29.12.2009

Я что-то упускаю или вам просто не нужен ArrayList<Person>?

person JRL    schedule 29.12.2009
comment
Список массивов использует индекс элемента для его поиска. Индекс для меня не важен и не имеет отношения к элементу. Я мог бы использовать indexOf (Object), а затем использовать результат с get, но разве это не было бы довольно неэффективно? Разве не пришлось бы дважды перебирать структуру данных? Это кажется очень плохим. Я буду часто этим заниматься, поэтому подумал, что лучше использовать хеш-карту. - person they changed my name; 30.12.2009
comment
С другой стороны, может быть, вам придется профилировать это, чтобы действительно быть уверенным. На этом этапе вы сохраняете список контактов, поэтому ArrayList кажется наиболее простым. Я бы побеспокоился об узком месте, когда вы его измеряете. Но у вас может быть предыдущий опыт, который говорит вам, что это будет узкое место, я не знаю. - person JRL; 30.12.2009

Я бы просто сохранил контакты в List<Person>. Например.

public class Person {
    private List<Person> contacts;
}

Что касается редактирования отдельного контакта, то это действительно не ответственность родителя Person. Он должен максимально добавлять / удалять контакты. Вы прекрасно можете сделать это с помощью contacts.add(otherPerson) или contacts.remove(otherPerson).

Если вы хотите отредактировать отдельный Person, который может быть одним из контактов, просто обработайте его независимо, например personDAO.find(personId), а затем обновите его соответствующим образом. На самом деле это также ответственность Person за редактирование собственных данных. При наличии хорошего ORM изменения будут отражены в списке контактов других Persons.

person BalusC    schedule 30.12.2009

Если вам нужно перебирать людей или требовать от них упорядочивания, рассмотрите TreeMap или TreeSet вместо хеширования.

person ZoFreX    schedule 30.12.2009