Heim  >  Artikel  >  Java  >  Beispielcode, der die Unterschiede und Zusammenhänge zwischen ==, equal und hashCode in Java ausführlich erklärt

Beispielcode, der die Unterschiede und Zusammenhänge zwischen ==, equal und hashCode in Java ausführlich erklärt

黄舟
黄舟Original
2017-03-14 11:25:011352Durchsuche


1. Übersicht

1. Konzept

  • ==: Die Operation Das Symbol generiert ein boolesches Ergebnis, das die Beziehung zwischen den Werten der -Operanden

  • gleicht : Objects Instanzmethode , vergleicht den Inhalt Objekten 🎜>Ist es derselbe? Das Objekt Der

    Hash-Wert
  • wird verwendet, um die

    Index-Position des Objekts in der Hash-Tabelle zu bestimmen. Es handelt sich tatsächlich um einen int-TypGanzzahl2. Vergleichsoperatoren==1. OperandenwertBasisDatentyp

    Variable

Es gibt acht grundlegende Datentypen in Java:

 

Gleitkommatyp

:
  • Dieser Satz deklariert eine Referenztypvariable, die derzeit keinem Objekt zugeordnet ist.

    Und verwenden Sie new, um ein Objekt zu generieren und dieses Objekt an str1 zu binden:
    Dann zeigt str1 auf dieses Objekt, und zu diesem Zeitpunkt bezieht sich auf Was In der Variablen str1 wird die Speicheradresse des Objekts im Speicher gespeichert, auf das sie zeigt, nicht der „Wert“ selbst, das heißt, es handelt sich nicht um eine direkt gespeicherte Zeichenfolge

    „Hallo“
  • . Die Referenzen hier sind den Zeigern in C/C++ sehr ähnlich.
    String str1;

2. Zusammenfassung
Daher gilt für den Vergleichsoperator ==:

str1= new String("hello");

Wenn der Typ des Operanden Basisdatentyp , dann bestimmt der Vergleichsoperator, ob die

-Werte

des linken und rechten Operanden gleich sind

    Wenn der Typ des Operanden
  • Referenzdatentyp ist, dann bestimmt der Vergleichsoperator die Speicheradresse des linken und rechte Operanden Sind sie gleich? Mit anderen Worten: Wenn zu diesem Zeitpunkt „true“ zurückgegeben wird, muss der Operator auf dasselbe Objekt reagieren.

  • 3. Equals-Methode Quelle Die Equals-Methode ist eine Instanzmethode in der Basisklasse Object. Daher haben alle Klassen, die von Object erben, diese Methode.   Deklaration im Objekt:

    2. Die Rolle der Gleichheitsmethode
  •  
Ursprüngliche Absicht:

Beurteilen Sie den Unterschied zwischen zwei Objekten

Ist der Inhalt

derselbe?
Um die Rolle der Equals-Methode intuitiver zu verstehen, schauen wir uns zunächst die Implementierung der Equals-Methode in der
Object-Klasse an
.

    public boolean equals(Object obj) {}

Offensichtlich

In der Object-Klasse wird die Methode „equals“ verwendet, um zu vergleichen, ob die Referenzen zweier Objekte gleich sind, das heißt, ob sie auf dasselbe Objekt verweisen.

  但我们都知道,下面代码输出为 true:

public class Main {
    public static void main(String[] args) {
        String str1 = new String("hello");
        String str2 = new String("hello");

        System.out.println(str1.equals(str2));
    }
}

原来是 String 类重写了 equals 方法:

public boolean equals(Object anObject) {   // 方法签名与 Object类 中的一致
    if (this == anObject) {     // 先判断引用是否相同(是否为同一对象),
        return true;
    }    if (anObject instanceof String) {   // 再判断类型是否一致,
        // 最后判断内容是否一致.
        String anotherString = (String)anObject;        
        int n = count;        
        if (n == anotherString.count) {        
        char v1[] = value;        
        char v2[] = anotherString.value;        
        int i = offset;        
        int j = anotherString.offset;       
         while (n-- != 0) {            
         if (v1[i++] != v2[j++])            
         return false;
        }        return true;
        }
    }    return false;
}

即对于诸如“字符串比较时用的什么方法,内部实现如何?”之类问题的回答即为:

使用equals方法,内部实现分为三个步骤:

  • 比较引用是否相同(是否为同一对象),

  • 判断类型是否一致(是否为同一类型),

  • 最后 比较内容是否一致

Java 中所有内置的类的 equals 方法的实现步骤均是如此,特别是诸如 Integer,Double 等包装器类。


3、equals 重写原则

对象内容的比较才是设计equals()的真正目的,Java语言对equals()的要求如下,这些要求是重写该方法时必须遵循的:

  • 对称性: 如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true” ;

  • 自反性: x.equals(x)必须返回是“true” ;

  • 类推性: 如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true” ;

  • 一致性: 如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true” ;

  • 对称性: 如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。

  • 任何情况下,x.equals(null)【应使用关系比较符 ==】,永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”


4、小结
 因此,对于 equals 方法:

  • 本意比较两个对象的 content 是否相同

  • 必要的时候,我们需要重写该方法,避免违背本意,且要遵循上述原则


四、hashCode 方法

1、hashCode 的来源
  hashCode 方法是基类Object中的 实例native方法,因此对所有继承于Object的类都会有该方法。
  
  在 Object类 中的声明(native方法暗示这些方法是有实现体的,但并不提供实现体,因为其实现体是由非java语言在外面实现的):

     public native int hashCode();

2、哈希相关概念
 我们首先来了解一下哈希表:

  • 概念 : Hash 就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出(int),该输出就是散列值。这种转换是一种  压缩映射,也就是说,散列值的空间通常远小于输入的空间。不同的输入可能会散列成相同的输出,从而不可能从散列值来唯一的确定输入值。简单的说,就是一种将任意长度的消息压缩到某一固定长度的消息摘要函数

  • 应用–数据结构 : 数组的特点是:寻址容易,插入和删除困难; 而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入和删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为 “链表的数组”,如图:

             Beispielcode, der die Unterschiede und Zusammenhänge zwischen ==, equal und hashCode in Java ausführlich erklärt
                               图1 哈希表示例

     Die linke Seite ist offensichtlich ein Array, und jedes Mitglied des Arrays ist eine verknüpfte Liste. Alle von dieser Datenstruktur enthaltenen Elemente enthalten einen Zeiger zur Verknüpfung zwischen Elementen. Wir weisen Elemente basierend auf ihren eigenen Merkmalen verschiedenen verknüpften Listen zu. Außerdem finden wir anhand dieser Merkmale die richtige verknüpfte Liste und suchen dann das Element aus der verknüpften Liste. Unter diesen ist die Methode zur Berechnung des Elementarray-Index basierend auf den Elementeigenschaften die Hashing-Methode.

  • Anwendungsbereich der Reißverschlussmethode: Grundlegende Datenstruktur zum schnellen Suchen und Löschen. Normalerweise kann die gesamte Datenmenge im Speicher abgelegt werden.

  • Wichtige Punkte:
    Hash-Funktionsauswahl für Zeichenfolgen, Ganzzahlen, Permutationen und spezifische entsprechende Hash-Methoden, eine davon ist Open Hashing wird auch als Zipper-Methode bezeichnet, und die andere ist geschlossenes Hashing, auch als offene Adressierungsmethode bezeichnet.


3. Kurze Beschreibung von hashCode

In Java
Die von der Object-Klasse definierte hashCode-Methode gibt unterschiedliche Ganzzahlen für verschiedene Objekte zurück. (Dies wird erreicht, indem die interne Adresse des Objekts in eine Ganzzahl konvertiert wird, aber die Programmiersprache JavaTM erfordert diesen Implementierungstrick nicht).

Der allgemeine Vertrag für

hashCode lautet:

  • Mehrere Aufrufe desselben Objekts während der Ausführung einer Java-Anwendung Die hashCode-Methode muss konsistent dieselbe ganze Zahl zurückgeben, vorausgesetzt, dass die zum Vergleich von Objekten mit „equals“ verwendeten Informationen nicht geändert wurden. Diese Ganzzahl muss nicht von einer Ausführung einer Anwendung zur anderen Ausführung derselben Anwendung konsistent sein.

  • Wenn zwei Objekte gemäß der Methode equal(Object) gleich sind, muss der Aufruf der Methode hashCode für jedes der beiden Objekte das gleiche ganzzahlige Ergebnis liefern.

  • Wenn die beiden Objekte gemäß der Methode equal(java.

    lang.Object) nicht gleich sind, rufen Sie hashCode für eine der beiden Methoden auf erfordern nicht, dass unterschiedliche ganzzahlige Ergebnisse liefert. Programmierer sollten sich jedoch darüber im Klaren sein, dass die Generierung unterschiedlicher ganzzahliger Ergebnisse für ungleiche Objekte die Leistung der Hash-Tabelle verbessern kann.  
    Um die Rolle von HashCode besser zu verstehen, müssen wir zunächst den Container in Java verstehen,
    da HashCode nur in Datenstrukturen nützlich ist, die Hashing-Algorithmen erfordern, wie HashSet, HashMap und Hashtable.

    In Java gibt es drei Arten von Sammlungen: eine ist Liste, die andere ist Warteschlange und die dritte ist Set. Die Elemente in den ersten beiden Sätzen sind geordnet und können wiederholt werden. Die Elemente im letzten Satz sind ungeordnet, aber die Elemente können nicht wiederholt werden.

    Hier liegt also ein ernsteres Problem: Wenn Sie sicherstellen möchten, dass sich Elemente nicht wiederholen, auf welcher Grundlage sollte dann beurteilt werden, ob sich zwei Elemente wiederholen? Dies ist die Methode

    Object.equals . Wenn Sie jedoch jedes Mal, wenn ein Element hinzugefügt wird, dies einmal überprüfen, ist die Anzahl der Vergleiche der zur Sammlung hinzugefügten Elemente sehr groß, wenn viele Elemente vorhanden sind. Mit anderen Worten: Wenn die Sammlung jetzt 1000 Elemente enthält, wird die Methode „equals“ 1000 Mal aufgerufen, wenn das erste 001-Element zur Sammlung hinzugefügt wird. Dies wird natürlich die Effizienz erheblich verringern. Daher hat Java das Prinzip der Hash-Tabelle übernommen. Auf diese Weise verwenden wir den Hash-Algorithmus, um für jedes in der Sammlung zu speichernde Element einen Wert zu berechnen und dann basierend auf diesem Wert die Position des Elements im Array zu berechnen. Wenn der Sammlung ein neues Element hinzugefügt wird, kann es daher in zwei Schritte unterteilt werden:

  • Rufen Sie zuerst die hashCode-Methode dieses Elements auf und dann basierend Der resultierende Wert berechnet, wo sich das Element im Array befinden sollte. Wenn sich an dieser Position kein Element befindet, speichern Sie es direkt an dieser Position.

  • Wenn sich an dieser Position bereits ein Element befindet Rufen Sie dann die Methode equal auf, um sie mit dem neuen Element zu vergleichen. Wenn es identisch ist, wird es nicht gespeichert. Andernfalls wird es in der verknüpften Liste gespeichert, die dieser Position entspricht (die Implementierung von HashSet, HashMap und Hashtable in Java). setzt das Element immer an den Anfang der verknüpften Liste).

4. equals und hashCode

Voraussetzung:

Wenn es um hashCode geht, müssen wir reden über die Methode equal. Beide sind Methoden in der Object-Klasse. Da die Object-Klasse die Basisklasse aller Klassen ist, können diese beiden Methoden in allen Klassen überschrieben werden.

  • Prinzip 1:

    Wenn x.equals(y) „true“ zurückgibt, dann muss der hashCode() von x und y gleich sein; 🎜>

    Prinzip 2:
  • Wenn x.equals(y) „false“ zurückgibt, dann kann der hashCode() von x und y gleich oder ungleich sein;
  • 原则 3 : 如果 x 和 y 的 hashCode() 不相等,那么 x.equals(y) 一定返回 “false” ;

  • 原则 4 : 一般来讲,equals 这个方法是给用户调用的,而 hashcode 方法一般用户不会去调用 ;

  • 原则 5 : 当一个对象类型作为集合对象的元素时,那么这个对象应该拥有自己的equals()和hashCode()设计,而且要遵守前面所说的几个原则。


5、实现例证

 hashCode()在object类中定义如下:

public native int hashCode();

 说明是一个本地方法,它的实现是根据本地机器相关的。

 String 类是这样重写它的:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence{
    /** The value is used for character storage. */
    private final char value[];     //成员变量1

    /** The offset is the first index of the storage that is used. */
    private final int offset;      //成员变量2

    /** The count is the number of characters in the String. */
    private final int count;       //成员变量3

   /** Cache the hash code for the string */
    private int hash; // Default to 0    //非成员变量

    public int hashCode() {    int h = hash;        int len = count;         //用到成员变量3
    if (h == 0 && len > 0) {        int off = offset;         //用到成员变量2
        char val[] = value;       //用到成员变量1
            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];       //递推公式
            }
            hash = h;
        }        return h;
    }
}

对程序的解释:h =  s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],由此可以看出,对象的hash地址不一定是实际的内存地址。


五、小结

  • hashcode是系统用来快速检索对象而使用

  • equals方法本意是用来判断引用的对象是否一致

  • 重写equals方法和hashcode方法时,equals方法中用到的成员变量也必定会在hashcode方法中用到,只不过前者作为比较项,后者作为生成摘要的信息项,本质上所用到的数据是一样的,从而保证二者的一致性


Das obige ist der detaillierte Inhalt vonBeispielcode, der die Unterschiede und Zusammenhänge zwischen ==, equal und hashCode in Java ausführlich erklärt. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen 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