hashCodeとequals


最近復習しているうちに、equals()とhashCode()を再理解しました.
equals()は,2つのオブジェクトが等しいか否かを判断するために用いられることが公認されている.hashCode()は、ハッシュ容器が効率的に動作するように設計されている.
どうしてそう言うの?Javaには、Hashtable、HashMapなどのハッシュコンテナがあります.これらのクラスのget(Object obj)メソッドなどを呼び出すと、コンテナの内部では、後続の操作のために現在のオブジェクトobjがコンテナに存在するかどうかを判断する必要があります.十分に存在するかどうかを判断するには、2つのオブジェクトが等しいかどうかを比較する必要があります.equals()を使用する必要があります.
しかしハッシュコンテナの要素が多い場合,equals()を使用するのは必然的に遅い.このとき、hashCode()という代替案を考えました.hashCode()はintタイプを返し、比較的速いです.しかし、これも問題になりました.
2つのオブジェクトに事実上2つの基準があると判定するのですか?もちろんそうではありません.冒頭で述べたように、hashCode()はハッシュコンテナで効率的に動作できるように設計されています.また、ハッシュコンテナでのみ、hashCode()を使用して比較オブジェクトが等しいかどうか、弱い比較を行います.
ハッシュコンテナのget(Object obj)メソッドを呼び出すと、彼はまず現在のコンテナに同じハッシュ値が存在することを確認し、存在しない場合はnullを返します.存在する場合は、現在のオブジェクトのequals()を呼び出します.メソッドは、ハッシュのオブジェクトが検索するオブジェクトと同じオブジェクトであるかどうかを比較し、そうでない場合はnullを返します.もしそうであれば、現在のハッシュコンテナに対応する値があることを示し、ハッシュのオブジェクトを返します.
このようにhashCode()法はハッシュコンテナの効率を向上させ,これがhashCode()の存在の意味である.hashCode()が等しいことを2つのオブジェクトが等しい必要非十分条件と見なすことができ,equals()が等しいことが十分条件である.
したがって、クラスをカスタマイズするときは、equals()とhashCode()を同時に書き換える必要があります.1 2つのオブジェクトのequals()が等しい場合、hashCode()は必ず等しいことを保証する必要があります.2つのオブジェクトのhashCode()が等しくない場合、hashCode()は必ず等しくありません.
import java.util.HashMap;


public class Demo {
	public static void main(String[] args) throws Exception{
		Person person=new Person("xyz",22);
		HashMap<Person,Integer> hashMap=new HashMap<Person,Integer>();
		hashMap.put(person, 1);
		System.out.println(hashMap.get(new Person("xyz",22)));
	}
}
class Person{
	private String name;
	private int age;
	public Person(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(this==obj)
			return true;
		if(obj instanceof Person){
			Person person=(Person) obj;
			if(this.age==person.getAge() && this.name.equals(person.getName()) )
				return true;
		}
		return false;
	}
//	@Override
//	public int hashCode() {
//		return this.name.hashCode()*10+this.age;
//	}
}

上のコードではhashCode()を注釈する前後の実行結果が異なり,hashCode()を注釈する場合,personと後に新しく作成されたPersonはequalsは同一のオブジェクトであるが,HashMapコンテナ内部でhashCode()を比較すると異なる要素であると考えられる.
したがって,equals()メソッドを書き換えるときはhashCode()メソッドを書き直さなければならないことを肝に銘じておく.
次にStringクラスのequalsメソッドとhashCodeメソッドを見てみましょう.
 public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
 public int hashCode() {
        int h = hash;//   0
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;//String        String     ASCII          
    }