Heim  >  Artikel  >  Java  >  Korrekte Verwendung von HashCode- und Equals-Methoden in Java

Korrekte Verwendung von HashCode- und Equals-Methoden in Java

高洛峰
高洛峰Original
2016-12-16 10:25:341293Durchsuche

In diesem Artikel werde ich Ihnen mein Verständnis von HashCode und Equals-Methoden erläutern. Ich bespreche ihre Standardimplementierungen und wie man sie richtig überschreibt. Ich werde auch eine Implementierung mit dem von Apache Commons bereitgestellten Toolkit durchführen.

Verzeichnis:

Verwendung von hashCode() und equal()

Überschreiben Sie die Standardimplementierung

Schreiben Sie hashCode mit dem Apache Commons Lang-Paket neu () und equal()

Dinge, die Sie beachten sollten

Etwas, worauf Sie bei der Verwendung von ORM besonders achten sollten

hashCode() und equal() sind in der Object-Klasse definiert. Diese Klasse ist die Basisklasse aller Java-Klassen, daher erben alle Java-Klassen diese beiden Methoden.


Verwendung von hashCode() und equal()

Die Methode hashCode() wird verwendet, um die eindeutige Ganzzahl eines bestimmten Objekts zu erhalten. Diese Ganzzahl wird verwendet, um zu bestimmen, wo das Objekt in einer HashTable-ähnlichen Struktur gespeichert ist. Standardmäßig gibt die Methode hashCode() der Klasse Object die Nummer der Speicheradresse zurück, an der dieses Objekt gespeichert ist.

Standardimplementierung überschreiben

Wenn Sie diese beiden Methoden nicht überschreiben, treten kaum Probleme auf, aber manchmal erfordert das Programm, dass wir die Standardimplementierung einiger Objekte ändern.

Lassen Sie uns einen Blick auf dieses Beispiel werfen.

public class Employee
{
    private Integer id;
    private String firstname;
    private String lastName;
    private String department;
 
    public Integer getId() {
        return id;
    }
    public void setId(Integer 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;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}

Die obige Employee-Klasse hat nur einige sehr grundlegende Attribute sowie Getter und Setter eine Situation, in der Sie zwei Mitarbeiter vergleichen müssen.

public class EqualsTest {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();
 
        e1.setId(100);
        e2.setId(100);
        //Prints false in console
        System.out.println(e1.equals(e2));
    }
}

Es besteht kein Zweifel, dass das obige Programm „false“ ausgibt, aber tatsächlich repräsentieren die beiden oben genannten Objekte einen Mitarbeiter. Echte Geschäftslogik möchte, dass wir wahr zurückgeben.
Um dieses Ziel zu erreichen, müssen wir die Methode „equals“ überschreiben.

public boolean equals(Object o) {
        if(o == null)
        {
            return false;
        }
        if (o == this)
        {
           return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}

Fügen Sie diese Methode zur obigen Klasse hinzu und EauqlsTest gibt true aus.
Also sind wir fertig? Nein, versuchen wir es mit einer anderen Testmethode.

import java.util.HashSet;
import java.util.Set;
 
public class EqualsTest
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee();
        Employee e2 = new Employee();
 
        e1.setId(100);
        e2.setId(100);
 
        //Prints 'true'
        System.out.println(e1.equals(e2));
 
        Set<Employee> employees = new HashSet<Employee>();
        employees.add(e1);
        employees.add(e2);
        //Prints two objects
        System.out.println(employees);
    }

Das obige Programm gibt zwei Ergebnisse aus. Wenn zwei Mitarbeiterobjekte gleich „true“ sind, sollte nur ein Objekt in Set gespeichert werden. Was ist das Problem?
Wir haben die zweite wichtige Methode hashCode() vergessen. Wie im JDK-Javadoc angegeben, müssen Sie, wenn Sie die Methode equal() überschreiben, auch die Methode hashCode() überschreiben. Wenn wir die folgende Methode hinzufügen, wird das Programm korrekt ausgeführt.

@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }

Verwenden Sie das Apache Commons Lang-Paket, um die Methoden hashCode() und equal() neu zu schreiben
Das Apache Commons-Paket bietet zwei hervorragende Klassen zum Generieren der Methoden hashCode() und equal(). Sehen Sie sich das Programm unten an.

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Employee
{
 private Integer id;
 private String firstname;
 private String lastName;
 private String department;
public Integer getId() {
    return id;
 }
 public void setId(Integer 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;
 }
 public String getDepartment() {
    return department;
 }
 public void setDepartment(String department) {
    this.department = department;
 }
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).
           toHashCode();
 }
@Override
 public boolean equals(Object o) {
    if (o == null)
       return false;
    if (o == this)
       return true;
    if (o.getClass() != getClass())
       return false;
    Employee e = (Employee) o;
       return new EqualsBuilder().
              append(getId(), e.getId()).
              isEquals();
    }
 }

Wenn Sie Eclipse oder eine andere IDE verwenden, stellt die IDE möglicherweise auch gut generierte hashCode()-Methoden und equal()-Methoden bereit.

Korrekte Verwendung von HashCode- und Equals-Methoden in Java

Dinge, die Sie beachten sollten

Versuchen Sie sicherzustellen, dass dieselbe Eigenschaft des Objekts zum Generieren der Methoden hashCode() und equal() verwendet wird. In unserem Fall verwenden wir die Mitarbeiter-ID.

Die eqauls-Methode muss konsistent sein (wenn das Objekt nicht geändert wurde, sollte equal den gleichen Wert zurückgeben)

Jedes Mal, wenn a.equals(b) verwendet wird, dann a.hashCode( ) muss mit b identisch sein.hashCode() ist gleich.

Beide müssen gleichzeitig neu geschrieben werden.

Etwas zu beachten bei der Verwendung von ORM

Wenn Sie ORM zum Verarbeiten einiger Objekte verwenden, müssen Sie sicherstellen, dass Sie Getter und Setter in hashCode()- und equal()-Objekten anstelle von direkter Referenz verwenden Mitgliedsvariablen. Da Mitgliedsvariablen in ORM manchmal träge geladen werden, sind diese Variablen nur dann wirklich verfügbar, wenn die Getter-Methode aufgerufen wird.

In unserem Beispiel kann dieses Problem beispielsweise auftreten, wenn wir e1.id == e2.id verwenden, es tritt jedoch nicht auf, wenn wir e1.getId() == e2.getId() verwenden. Diese Frage .


Weitere Artikel zur korrekten Verwendung von HashCode- und Equals-Methoden in Java finden Sie auf der chinesischen PHP-Website!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn