# V6049. Classes that define 'equals' method must also define 'hashCode' method.

Анализатор обнаружил пользовательский тип, который переопределяет метод 'equals', но не переопределяет метод 'hashCode', и наоборот. Это может привести к неправильному функционированию пользовательского типа в сочетании с такими коллекциями как HashMap, HashSet и Hashtable, так как они активно используют 'hashCode' и 'equals' в своей работе.

Рассмотрим пример с использованием HashSet:

    public class Employee {

      String name;
      int age;

      public Employee(String name, int age) {
        this.name = name;
        this.age = age;
      }

      public String getName() { return name; }

      public void setName(String name) { this.name = name; }

      public int getAge() { return age; }

      public void setAge(int age) { this.age = age; }

      public String getFullInfo() {
        return this.name + " - " + String.valueOf(age);
      }

      @Override
      public boolean equals(Object obj) {
        if (obj == this)
          return true;
        if (!(obj instanceof Employee))
          return false;
        Employee employee = (Employee) obj;
        return employee.getAge() == this.getAge()
                && employee.getName() == this.getName();
      }
    }

    public static void main(String[] args)
    {
      HashSet<Employee> employees = new HashSet<>();
      employees.add(new Employee("OLIVER", 25));
      employees.add(new Employee("MUHAMMAD", 54));
      employees.add(new Employee("OLIVER", 25));

      employees.forEach(arg -> System.out.println(arg.getFullInfo()));
    }

В результате работы программы на консоль будет выведено:

    OLIVER - 25
    MUHAMMAD - 54
    OLIVER - 25

Как видим, несмотря на то, что тип 'Employee' переопределяет метод 'equals', этого недостаточно. В ходе выполнения программы нам не удалось получить ожидаемого результата, и коллекция содержит повторяющиеся элементы. Для устранения этой проблемы в объявление типа 'Employee' необходимо добавить переопределение метода 'hashCode':

    public class Employee {

    ...

    @Override
    public boolean equals(Object obj) {
      if (obj == this)
        return true;
      if (!(obj instanceof Employee))
        return false;
      Employee employee = (Employee) obj;
      return employee.getAge() == this.getAge()
              && employee.getName() == this.getName();
    }

    @Override
    public int hashCode() {
        int result=17;
        result=31*result+age;
        result=31*result+(name!=null ? name.hashCode():0);
        return result;
    }
    }

    public static void main(String[] args)
    {
      HashSet<Employee> employees = new HashSet<>();
      employees.add(new Employee("OLIVER", 25));
      employees.add(new Employee("MUHAMMAD", 54));
      employees.add(new Employee("OLIVER", 25));

      employees.forEach(arg -> System.out.println(arg.getFullInfo()));
    }

Вновь выполним программу. В результате на консоль будет выведено:

    MUHAMMAD - 54
    OLIVER – 25

Мы получили корректный результат: коллекция содержит только уникальные элементы.

Данная диагностика классифицируется как:

CERT-MET09-J