JavaRush /Blogue Java /Random-PT /Sobrecarregando os métodos equals() e hashCode() em Java
Coder
Nível 17

Sobrecarregando os métodos equals() e hashCode() em Java

Publicado no grupo Random-PT

Substituindo os métodos equals() e hashCode() em Java

Equalse hashCodesão os métodos fundamentais declarados na classe Objecte contidos nas bibliotecas Java padrão. Sobrecarregando os métodos equals() e hashCode() em Java - 1O método еquals()é usado para comparar objetos e hashCodegerar um código inteiro para o objeto. Esses métodos são amplamente utilizados nas bibliotecas padrão Java ao inserir e recuperar objetos em arquivos HashMap. O método equaltambém é usado para garantir que apenas objetos únicos sejam armazenados em HashSetoutras Setimplementações, bem como em quaisquer outros casos onde os objetos precisem ser comparados. A implementação padrão do método equals()na classe java.lang.Objectcompara as referências aos endereços de memória que as variáveis ​​armazenam e retorna trueapenas se os endereços corresponderem, ou seja, as variáveis ​​se referem ao mesmo objeto. Java recomenda substituir os métodos equals()e hashCode()se você espera que a comparação seja feita de acordo com a lógica natural ou lógica de negócios. Muitas classes nas bibliotecas Java padrão as substituem, por exemplo, a classe Stringsubstitui equalspara retornar truese o conteúdo dos dois objetos que estão sendo comparados for o mesmo. A classe wrapper substitui Integero método equalpara realizar uma comparação numérica e assim por diante. Como Java HashMaptambém depende de métodos e para comparar seus e , Java oferece as seguintes regras para substituir esses métodos: HashTableequals()hashCode()keyvalues
  1. Reflexividade: O objeto deve ser igual a si mesmo.
  2. Simétrico: se a.equals(b)retornar true, então b.equals(a)também deverá retornar true.
  3. Transitividade: se a.equals(b)retornar truee b.equals(c)também retornar true, então c.equals(a)também deverá retornar true.
  4. Consistência: chamadas repetidas a um método equals()devem retornar o mesmo valor, desde que alguns valores das propriedades do objeto não sejam alterados. Ou seja, se dois objetos são iguais em Java, então eles serão iguais enquanto suas propriedades permanecerem inalteradas.
  5. Comparação null: O objeto deve ser verificado null. Se o objeto for igual a null, então o método deverá retornar false, não NullPointerException. Por exemplo, a.equals(null)deve retornar false.

Acordo entre iguais e hashCode em Java

  1. Se os objetos forem iguais nos resultados da execução do método equals, então eles hashcodedeverão ser iguais.
  2. Se os objetos não forem iguais nos resultados da execução do método equals, eles hashcodepoderão ser iguais ou diferentes. No entanto, para melhorar o desempenho, é melhor que objetos diferentes retornem códigos diferentes.

Как переопределять метод equals в Java

  1. @Override
    public boolean equals(Object obj) {
    /*1. Check*/if (obj == this) {
    /*and return */ return true;
             }
  2. Проверьте an object на null, а также проверьте, чтобы an objectы были одного типа. Не делайте проверку с помощью instanceof так How такая проверка будет возвращать true для подклассов и будет работать правильно только в случае если ваш класс объявлен How immutable. Вместо этого можно использовать getClass();

    if (obj == null || obj.getClass() != this.getClass()) {
                return false;
    }
  3. Объявите переменную типа, который вы сравниваете, и приведите obj к этому типу. Потом сравнивайте каждый атрибут типа начиная с численных атрибутов (если имеются) потому что численные атрибуты проверяются быстрей. Сравнивайте атрибуты с помощью операторов И и ИЛИ (так называемые short-circuit logical operators) для объединения проверок с другими атрибутами.

    Person guest = (Person) obj;
            return id == guest.id && (firstName == guest.firstName ||
                (firstName != null && firstName.equals(guest.getFirstName())))
                    && (lastName == guest.lastName || (lastName != null &&                      lastName .equals(guest.getLastName())));
    }
Полный пример переопределения метода equals в Java
/** * Person class with equals and hashcode implementation in Java * @author Javin Paul */
public class Person {
    private int id;
    private String firstName;
    private String lastName;

    public int getId() { return id; }
    public void setId(int id) { this.id = id;}

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    @Override
    public boolean equals(Object obj) {
    if (obj == this) {
        return true;
    }
    if (obj == null || obj.getClass() != this.getClass()) {
        return false;
    }

    Person guest = (Person) obj;
    return id == guest.id
        && (firstName == guest.firstName
            || (firstName != null &&firstName.equals(guest.getFirstName())))        && (lastName == guest.lastName
            || (lastName != null && lastName .equals(guest.getLastName())
            ));
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());             result = prime * result + id; result = prime * result +
        ((lastName == null) ? 0 : lastName.hashCode()); return result;
    }
 }

Распространенные ошибки при переопределении equals в Java

  1. Вместо того, чтобы переопределять метод equals (Override) программист перегружает его (Overload)Синтаксис метода equals() в классе Object определен How public boolean equals(Object obj), но многие программисты ненароком перегружают метод: public boolean equals(Person obj) - instead of Object в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-за static binding. Таким образом, если вы вызовете этот метод для an object своего класса, то метод не просто скомпorруется, а даже сделает это корректно. Однако, если вы положите ваш an object в коллекцию, например ArrayList и вызовете метод contains(), работа которого основана на методе equals(), то метод contains не сможет обнаружить ваш an object.

  2. При переопределении метода equals() не проверять на null переменные, что в конечном итоге заканчивается NullPointerException при вызове equals(). Ниже представлен корректный code.

    firstname == guest.firstname || (firstname != null &&
         firstname.equals(guest.firstname));
  3. Третья распространенная ошибка это не переопределять метод hashCode(), а только equals(). Вы обязаны переопределять оба метода equals() и hashCode() в Java. Метод hashCode используется в hash -коллекциях(например HashSet), и чем меньше будет коллизий (одинаковый code при разных an objectх) тем эффективнее эти коллекции будут работать с an objectми вашего класса.

  4. Последняя распространенная ошибка программистов в том, что при переопределении метода equals() не сохраняется соответствие между методами equals() и compareTo(), что является неформальным требованием для избежания хранения дубликатов в Set (SortedSet, TreeSet).

Подсказки How писать в Java метод equals

  1. Большинство IDE такие How NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов equals() и hashCode(). В Eclipse нажмите правую кнопку -> source -> generate equals() и hashCode().

  2. Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на equalsство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.

  3. При переопределении hashCode() в Java удостоверьтесь в использовании всех полей, что были использованы в методе equals().

  4. Stringe classes wrapper como Integer, Floate Doublesubstituem o método equals(), mas StringBuffernão substituem.

  5. Sempre que possível, crie campos immutableusando finalvariáveis ​​em Java.

  6. Ao comparar Stringobjetos, use equals()o operador ==.

  7. Dois objetos logicamente iguais, mas carregados de objetos diferentes, ClassLoadernão podem ser iguais. Lembre-se de que a verificação com getClass()retornará falsese a classe do carregador for diferente.

  8. Use @Overridea anotação também no método . hashCode, pois isso evita erros sutis, como o valor de retorno do int.No entanto, alguns programadores retornam long.

PS Caros colegas! Achei este artigo útil para resolver problemas de nível 21! Desejo-lhe boa sorte na análise deste tema, use a tradução! Espero que vocês me ajudem a aumentar minha classificação, pois agora não posso nem deixar comentários neste fórum. Muito obrigado a todos! Artigo original omiti alguns pontos por falta de tempo livre, mas traduzi tudo o que você precisa saber para resolver problemas do nível 21.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION