11

だから私は hashcode() と equals() メソッドについて質問があります

両方のメソッドをオーバーライドする非常に基本的なプログラムを書いたとしましょう

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;
   }

}

次に、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());
       }


    }

}

今問題は、同じ empid で常に 3 回呼び出された equals() で Alex を再度追加しようとしたときです。

インデックス n ハッシュマップがないため、以前に追加された Alex で最初にチェックされた場合、true が返され、他の 2 つの要素 (ピーターとマーティン) に対して呼び出されるべきではありませんが、常に 3 回呼び出されます。

どうして..??

同じバケット内のオブジェクトにもインデックスがあります..??

4

4 に答える 4

14

EqualshashCode要素を追加および削除する際に、Java ハッシュ コレクション内のメソッドの後に常に呼び出されます。その理由は、指定されたバケットに要素がすでに存在する場合、JVM はそれが配置しようとしている要素と同じかどうかをチェックするためです。equals が false を返す場合、要素は同じバケットに追加されますが、バケットのリストの最後に追加されます。したがって、同じバケットに要素が 1 つではなく、要素のリストがあるだけです。

要素を取得している間、最初に hashCode が呼び出されて目的のバケットに到達し、次に equals を使用してリストがスキャンされ、目的の要素がフェッチされます。

の理想的な実装でhashCodeは、各バケットのリストのサイズが 1 であることを確認します。したがって、要素の取得は O(1) の複雑さを使用して行われます。ただし、バケットのリストに複数の要素が格納されている場合、要素の取得は O(n) complexiy によって行われます。ここで、n はリストのサイズです。

ところで、HashSet の場合、バケットで作成されたリストはなく、ハッシュコードと等号が同じ場合、オブジェクトは単純に置き換えられます。ist 作成動作はハッシュマップにあります。

于 2013-07-29T08:45:19.693 に答える
3

Ajava.util.HashSetは、java.util.HashMapストレージとして a を使用します。java.util.HashMapは、リンクされたオブジェクトEntryを使用して、マップ内のバケットを表します。ソースコードをたどると、次のコンストラクターに到達しますjava.util.HashMap.Entry

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

これから、新しいアイテムがバケットの先頭 (バケットEntry nの最初を表す) に追加されていることがわかります。したがって、この場合、バケット内のアイテム (それぞれのハッシュ コードが同じEntryであるため、バケットは 1 つしかありません) Employee) は次の順序になります。

Martin -> Peter -> Alex

したがって、Alex を 2 回目に追加すると、Alex に到達する前に各値が等しいかどうかがチェックされます。

于 2013-07-29T09:01:21.857 に答える