Equals и HashCode? Java

В не на писании equals, то, что делает этот метод, он состоит в том, чтобы сравнивать hashCode инстанций?

Зачем он помогает мне на писании метода hashCode?

13
задан 12.03.2016, 23:43
2 ответа

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

...
public native int hashCode();

...

public boolean equals(Object obj) {
    return (this == obj);
}
...

Относительно первого метода, цели hashCode он состоит в том, чтобы возвращать целое число, которое 'идентифицирует' объект, когда он сохраняет в структуре данных известной в качестве HashMap (или другие как Hashtable, HashSet), цель которого состоит в том, чтобы хранить набор стоимости (формы, сходной с одним ArrayList или договоренность). Эти структуры, за исключением каких-то различий, сохраняются данные о следующей форме:

Hashtable

Захотев сохранять объект в этой структуре, он называется в метод hashCode(), поскольку я упомянул, этот возвращает целое число, которое структура использует, чтобы принимать решение в каком 'ящике' (bucket) он будет сохранять эту информацию. Сейчас, если я хочу вернуть объект, который я сохранял, я звоню в метод hashCode снова, и так я определяю какого ящика я должен возвращать объект (как когда я сохраняю данные ключ / стоимость, он звонит в метод hashCode ключа, чтобы получать соответствующую стоимость). Цель сохранять данные об этой форме и звонить в метод состоит в том, чтобы удаваться хранить и возвращать информацию в постоянном времени (что не происходит всегда, но он приближается). Тот, за которым не последует это, зависит, почти всегда, от стоимости, которая возвращает метод hashCode () для каждого объекта.

Давайте предполагать, что мы сохраняем 3 объекта в этой структуре и методе hashCode 3 возврати 0, это означает, что 3 объекта gurdarán в ящике 0. Если я захочу вернуть их, случится, что я должен пробегать сейчас объекты, которые он сохранял в этом ящике, чтобы определять, который тот, которого я хочу. Следовательно, метод hashCode () этих объектов не является полезным, так как то, что получают, состоит, в том, чтобы после того, как сохраняет эти элементы, они остались рассеянными единообразной формы во всей структуре (что они остались самое меньшее количество пустых ящиков, и что нет ящиков, где сохраняли многие другие элементы, чем другие).

Относительно осуществления метода hashCode класса Object, идентификатор native укажи на то, что это ответственность составителя определять, как он реализует эту работу. Во всех осуществлениях, которые я проверил, родной формы возврати числовое представление 'адреса памяти', в которой является помещенным объект. Эта кажется хорошей назначенной по умолчанию стратегией, но у нее есть большая проблема: есть многие другие адреса памяти, чем 'число ящиков' а следовательно структура решает проблему (снова, это также зависит от осуществления) распределяя ему ящик число hashcode()%MAX_LENGTH где MAX_LENGTH - максимальный размер договоренности. Тогда, в большее количество элементов, которое он нужно сохранять, больший это вероятность, что были ящики в структуре, у которых был бы излишек элементов.

В пользу такого мотива, если Вы нуждаетесь в том, чтобы хранить элементы в этом типе структур, Java советуй sobreescribir этот метод. Какие-то IDEs как Затмение или Netbeans позволяют производить метод hashCode начиная со свойств класса, и с этим это достаточно, чтобы решать эту проблему.

На втором методе, equals(), назначенное по умолчанию осуществление класса Object она ясная: сравни ссылки между объектами. Так что не sobreescribirlo, определив класс, это очень плохая идея, потому что не было бы никакого различия между тем, чтобы звонить в equals() и использовать оператор ==. Документация ясная, указав на характеристики, которые должны быть у этого метода, сравнив:

  1. Рефлексивность: если я сравниваю объект с собой самим, будь должен возвращаться true.
  2. Симметрия: если я сравниваю объект A с объектом B, и он возвращается true, тогда сравнение объекта B с объектом A также должно возвращаться true.
  3. Transitividad: если я сравниваю объект A с объектом B, и он возвращается true и я сравниваю объект B с другим объектом C и возвратись true, сравнив объект A с объектом C будь должен возвращаться true.
  4. Консистенция: если объекты A и B они не изменяются, последующие призывы к методу должны возвращать ту же стоимость.

Итак, поскольку поймет, метод equals() он не звонит в метод hashCode(), тогда: почему sobreescribir метод hashCode() когда sobreescribe метод equals()? самый простой ответ, - потому что документация это предлагает: если два объекта равны, они должны считать ту же стоимость возвращенной из-за hashCode(). Несмотря на то, что это подсказка, снова операция в этих структурах показывает, почему он необходим: если у двух объектов будет тот же hashCode, оба объекта будут сохранять в том же ящике, структура использует сейчас метод equals() внутри этого ящика, чтобы определять, который соответствует с попросившим, и для этого он зависит от того, что Вы есть sobreescrito метод, иначе не гарантирует правильный результат.

Вкратце:

  • Если sobreescribe метод equals() рекомендуемый sobreescribir также метод hashCode() чтобы сохранять контракт между обоими методами: два равных объекта должны возвращать ту же стоимость hash. Метод equals() он не звонит в метод hashCode() чтобы определять равенство двух объектов.
  • Это рекомендуемый, из-за того, что не говорит обязательно, sobreescribir метод equals() потому что назначенное по умолчанию осуществление не много помощи.
  • Если два объекта не равны, не является необходимым sobreescribir метод hashCode(), даже, два различных объекта могут возвращать стоимость hash равные.
  • Если он нуждается в том, чтобы сохранять объекты в примечательных структурах ранее (HashMap и сходные) это абсолютно необходимо, что sobreescriba метод hashCode(), иначе он получит неожиданные результаты или нежелательные, когда он реализует операции сохранения, консультирования или удаления данных.
15
ответ дан 24.11.2019, 14:44

Нет. То, что делает метод equals он состоит в том, чтобы оценивать, если объект равен другому. Если класс не на escribe метод equals, тогда результат использования equals это будет тот же самый, оператор использует == между объектами. Метод hashCode не будь присоединен с использованием оценки метода equals.

Метод hashCode служит для того, чтобы получить код hash, что был бы идентификатором объекта. Этот hash используется в каких-то коллекциях как HashSet, HashMap, LinkedHashSet, LinkedHashMap, ConcurrentHashMap, между другими. hash то, что он делает, состоит в том, чтобы помогать в контейнер помещать элемент в структуре коллекции и помогает искать, если объект с выражением hash уже существует, это, чтобы гарантировать время поисков O (1) (понимая, что число столкновений низкое).

Пример алгоритма того, как оно функционирует HashSet#add, где используются методы hashCode и equals. (Это идея, реальное осуществление сложнее и использует больше механизмов, чтобы уверять, нужно увеличивать ли или уменьшать размер внутренней структуры, но это не приходит в случай)

//es pseudocódigo, no es código Java
//se utiliza una matriz para guardar los elementos
Object[][] conjunto = ...
metodo agregar (elemento)
    int hash = nuevo.hashCode();
    si (hash < conjunto.length)
        //pueden haber varios elementos con el mismo hash
        //por ello se utiliza una matriz
        //el hash ayuda a 
        Object[] elementosConMismoHash = arreglo[hash];
        var encontrado = falso;
        para cada Object actual en elementosConMismoHash
            si actual.equals(nuevo) entonces
                encontrado = verdadero;
                romper para;
            fin si
        fin para
        si no fue encontrado entonces
            agregar nuevo en elementosConMismoHash
        fin si
    fin si
fin metodo

Поскольку ты можешь видеть, hashCode он используется как идентификатор, но могут существовать несколько элементов с тем же результатом hashCode. Это не гарантирует, что объекты были равны посредством использования equals.

2
ответ дан 24.11.2019, 14:44
  • 1
    > " М и # 233; каждый hashCode не est и # 225; присоединенный с использованием evaluaci и # 243; n м и # 233; каждый equals. и quot; Верно. Но, как он говорит другой ответ, важно гарантировать, что, если два объекта - " iguales" (equals возвращается true), тогда оба должны возвращать того же самого hashCode. Противоположность, конечно, не является верной (два objectos отличные могут возвращать тот же hashCode – leonbloy 13.03.2016, 16:21
  • 2
    Оба быть должным и # 237; an, они не должны. И это из-за поведения в вышеупомянутых коллекциях. –  13.03.2016, 17:25

Теги

Похожие вопросы