Hashcode java и его формирование

192
16 июля 2018, 03:30

Подскажите пожалуйста, должен ли Hashcode объекта измениться если его поля изменились?

Answer 1

Ни фига не должен, смотрим сюда:

public class HelloWorld {
  public static void main(String[] args) {
    //создаем объект 
    MyMutable myMutable = new MyMutable(1, "Hello");
    System.out.println("intValue="+myMutable.getIntValue()+", stringValue="+myMutable.getStringValue()+", hashcode="+myMutable.hashCode());
    //мутируем (меняем) его свойства
    myMutable.setIntValue(2);
    myMutable.setStringValue("World!");
    //проверяем hashCode()
    System.out.println("intValue="+myMutable.getIntValue()+", stringValue="+myMutable.getStringValue()+", hashcode="+myMutable.hashCode());
  }
}
class MyMutable {
  private int intValue;
  private String stringValue;
  public MyMutable(int intValue, String stringValue) {
    this.intValue=intValue;
    this.stringValue=stringValue;
  }
  public void setIntValue(int intValue) {
    this.intValue=intValue;
  }
  public int getIntValue() {
    return this.intValue;
  }
  public void setStringValue(String stringValue) {
    this.stringValue=stringValue;
  }
  public String getStringValue() {
    return this.stringValue;
  }
}

Вывод:

intValue=1, stringValue=Hello, hashcode=1829164700

intValue=2, stringValue=World!, hashcode=1829164700

Специально ввел 2 разных поля, все равно при их изменении hashCode() не пересчитывается и остается прежним.

Update

по следам дискуссии в комментариях:

1) В дефолтной реализации hashCode() он не будет меняться при мутации объекта

2) Чтобы он менялся необходимо переопределять hashCode(), например для приведенного примера приблизительно так:

public int hashCode() {
   return super.hashCode()+
       this.intValue+
       ((this.stringValue==null?0:this.stringValue.hashCode());
}
Answer 2

https://habr.com/post/168195/

Одинаковые объекты — это объекты одного класса с одинаковым содержимым полей.

Если объекты одинаковые, то и хеш-коды одинаковые (но не наоборот, см. правило 3).

Answer 3

Да, должен. Вот что по этому поводу пишут в документации:

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

Это следует из второго пункта и выделенной части первого. Но стоит иметь ввиду, что реализация по умолчанию метода hashCode этим принципам не следует, поэтому её всегда надо переопределять.

Answer 4

Все просто:
Если при описании своего объекта вы не переопределяете метод hashcode, то при его инициализации(вызов new) ему присваивается идентификационный хеш - hash по умолчанию. Делается это при помощи стандартного нативного метода.
В этом случае поля вашего объекта никак не влияют на формирование hashcode, соответственно любые изменения этих полей не приведут к изменению hashcode. Стоит учитывать, что создание нового аналогичного объекта не гарантирует совпадение hashcode
Если же вы явно переопределили метод hashcode и вычисление hash - объекта завязали на значение своих полей, то при их изменении hashcode так же изменится

Answer 5

Правильнее было бы использовать примерно такую модель, коль вы решили использовать собственный калькулятор хеша:

public class Test
{
    private int _a;
    private int _b;
    private int _c;
    public Test(int a, int b, int c)
    {
        _a = a;
        _b = b;
        _c = c;
    }
    @Override
    public int hashCode()
    {
        return _a ^ _b ^ _c;
    }
}

И не обязательно возвращать сгенерированный самой JVM хешкод объекта при запросе через super.hashcode(), если изменилось какое-то условие. На мой взгляд это моветон.

READ ALSO
Тетрис на Android

Тетрис на Android

Как усовершенствовать метод удаления заполненных линий? Чтобы заполненная линия изменялась на конкретную текстуру из класса Assets, а потом...

193
Cмаппить поле из типа определенным пользователем в cassandra с полем в java

Cмаппить поле из типа определенным пользователем в cassandra с полем в java

Как можно смаппить поле из типа определенным пользователем с полем в java со spring data

205
создание background через переопределение paintComponent

создание background через переопределение paintComponent

помогите разобраться, хочу сделать background (добивать изображение на основной фон), собственно добавление идет строками

164
Ускорить/Оптимизировать

Ускорить/Оптимизировать

Необходимо получить все данные игрока из базы данных, для проверки насколько это быстро произойдет я создал цикл из 100 юзеров

223