2013-07-29 11 views
9

, so habe ich eine Frage an hashcode() und equals() Methodehashcode() und equals() Methode

Sagen wir, ich schreibe nur ein sehr einfaches Programm overridng sowohl die methodes

import java.util.*; 

class Employee 
{ 
    private String name; 
    private int empid; 


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


    public int getEmpid() 
    { 
     return empid; 
    } 


    public String getName() 
    { 
     return name; 
    } 


    public boolean equals(Object obj) 
    { 
     System.out.println("equals has just been called..."); 
     Employee e1=(Employee)obj; 
     return ((name.equals(e1.name)) && (empid==e1.empid)); 
    } 


    public int hashCode() 
    { 
     System.out.println("hashcode called..."); 
     return empid; 
    } 

} 

Dann lassen Sie uns sagen, dass ich eine andere Klasse schreiben, um die Elemente in HashSet

class Five 
{ 
    public static void main(String args[]) 
    { 
     HashSet hs1=new HashSet(); 
     hs1.add(new Employee("Alex",25)); 
     hs1.add(new Employee("Peter",25)); 
     hs1.add(new Employee("Martin",25)); 
     hs1.add(new Employee("Alex",25)); 


     Iterator itr=hs1.iterator(); 

     while(itr.hasNext()) 
     { 
      Employee e=(Employee)itr.next(); 
      System.out.println(e.getEmpid()+"\t"+e.getName()); 
     } 


    } 

} 

jetzt hinzufügen und wiederholen die Frage ist, wenn ich versuche, Alex wieder hinzuzufügen mit der gleichen die equals() EmpID immer cal habe dir mal

wie es ist kein index n hashmap also im fall, wenn es zuerst mit zuvor hinzugefügtem Alex überprüft wird, wird es wahr und sollte nicht für die anderen zwei elemente (peter und martin) genannt werden aber gleich heißt immer 3 mal

warum .. ??

ist Objekte in gleichen Eimer haben auch den Index .. ??

+0

Ich würde mir den HashSet Quellcode ansehen. Aus dem Speicher wird es tatsächlich zu einer Map hinzugefügt, so dass ich annehme, dass indexOf und equals mehrmals verwendet werden. – RNJ

+0

ankur Lathinopss meine que ist anders – sandiee

Antwort

12

Equals wird immer nach der hashCode-Methode in einer Java-Hash-Sammlung beim Hinzufügen und Entfernen von Elementen aufgerufen. Wenn sich bereits ein Element im angegebenen Bucket befindet, prüft JVM, ob es dasselbe Element ist, das es zu setzen versucht. Falls das Gleichheitszeichen false zurückgibt, wird das Element zum selben Bucket aber am Ende der Liste im Bucket hinzugefügt. So, jetzt haben Sie nicht nur ein einzelnes Element im selben Eimer, sondern eine Liste von Elementen.

Nun, während das Element abgerufen wird, wird zuerst hashCode aufgerufen, um den gewünschten Bucket zu erreichen, und dann wird die Liste mit dem Equals gescannt, um das gewünschte Element zu holen.

Die ideale Implementierung von hashCode wird sicherstellen, dass die Größe der Liste in jedem Bucket 1 ist. Und daher wird das Abrufen von Elementen mit O (1) -Komplexität durchgeführt. Aber wenn es mulitple Elemente in der Liste auf einem Eimer gespeichert sind, dann ist das retreival des Elements wird durch O (n) complexiy erfolgen, wobei n die Größe der Liste ist.

Btw bei HashSet keine Liste gibt auf den heißen Stein, sondern das Objekt ersetzt wird einfach erstellt, wenn hashcode und equals gleich sind. Das Erstellungsverhalten ist in hashmap.

+2

Ich denke, dass der Aufruf der hashCode-Methode vom Aufruf der equals-Methode gefolgt wird ... – Puce

+1

@Puce Nein, hashCode wird immer zuerst aufgerufen, um den Bucket zu erhalten, und dann wird equals aufgerufen, um die Dinge in diesem Bucket zu überprüfen. –

+0

juned ahsan- thnx sir .. es hat einige zeit gedauert, aber jetzt habe ich es und die erklärung der komplexität ist der punkt ich will – sandiee

0

Mehrere Objekte mit demselben Hash werden als LinkedList gespeichert und neue Elemente werden unter HEAD hinzugefügt. Also in Ihrem Fall, da alle den gleichen Hash haben, ist LinkedList in folgender Reihenfolge:

Martin-> Peter-> Alex.

Wenn Sie ein weiteres "Alex" hinzufügen, wird die Liste von HEAD durchlaufen.

Zum Test:

public boolean equals(Object obj) 
    { 
     Employee e1=(Employee)obj; 
     System.out.println(this.name + "'s equals has just been called against " + e1.name); 
     return ((name.equals(e1.name)) && (empid==e1.empid)); 
    } 
3

Während Einsatzes der HashSet ersten Anrufe der hashCode und sieht in dem Eimer der neue Wert gehört. Er sieht, dass es bereits drei Einträge (alle mit dem hashCode()25).

vergleicht also dann von equals() verwenden.Und da es 3 Einträge gibt, muss es alle Einträge überprüfen, die dazu führen, dass equals() dreimal aufgerufen wird.

+1

Ich dachte ursprünglich, dass er den 'equals()' und 'hashCode()' Vertrag auch verletzt, aber wie konnte es überhaupt irgendetwas wirklich beeinflussen? Wenn sie den gleichen 'empid' haben, werden sie dem gleichen Array-Slot zugeordnet, und dann wird 'equals' verwendet, um zu sehen, ob die 'names' übereinstimmen. Ich kann kein Problem sehen ... –

+3

Die Methoden 'equals' und' hashCode' sehen für mich gut aus - das 'equals' verwendet sowohl' name'- als auch 'empid'-Felder, während der' hashCode' nur 'empid' verwendet. Dies bestätigt nicht den Vertrag, der besagt, dass gleiche Objekte den gleichen Hash-Code haben sollten, aber der gleiche Hash-Code bedeutet nicht, dass die Objekte gleich sind. –

+0

Eigentlich, ich denke, es muss Einträge nur vergleichen, solange eques false zurückgibt, kann aber aufhören, sobald equals wahr zurückgibt. Das bedeutet also wahrscheinlich, dass der erste Eintrag ("Alex", 25) aus irgendeinem Grund am Ende der Liste steht? – Puce

3

Eine java.util.HashSet verwendet eine java.util.HashMap als Speicher. A java.util.HashMap verwendet ein verknüpftes Objekt Entry, um die Buckets in der Karte darzustellen. Wenn Sie durch den Quellcode folgen, werden Sie auf die contructor von java.util.HashMap.Entry erhalten:

Entry(int h, K k, V v, Entry<K,V> n) 
{ 
    value = v; 
    next = n; 
    key = k; 
    hash = h; 
} 

Hieraus kann man sehen, dass neue Objekte auf den Anfang des Eimers hinzugefügt werden (die Entry n die erste Entry der Schaufel darstellt) in Ihrem Fall, so dass die Elemente in dem Eimer (es gibt nur eine einzige Schaufel, da der Code Hash für jeden Employee das gleiche ist) werden in der Reihenfolge sein:

Martin -> Peter -> Alex 

daher beim Hinzufügen von Alex ein zweites Mal, wobei jeder Wert wird auf Gleichheit überprüft, bevor man zu Alex kommt.