위키 백과의 해시 코드 정보 :
Java 프로그래밍 언어에서 모든 클래스는 암시 적으로 또는 명시 적으로 Hashcode () 메소드를 제공하며, 이는 클래스 인스턴스에 저장된 데이터를 단일 해시 값 (32 비트 서명 된 정수)으로 소화합니다.
해시 코드는 객체 인스턴스에 저장된 모든 데이터를 기반으로 32 비트 정수를 추출합니다. 이 정수의 목적은 인스턴스의 독창성을 나타내는 것입니다. MD5 코드와 다소 유사하며 각 파일은 MD5 알고리즘을 통해 고유 한 MD5 코드를 생성 할 수 있습니다. 그러나 Java의 해시 코드는 실제로 각 객체에 대해 고유 한 해시 코드를 생성하기 위해 해시 코드를 구현하지 않으며 여전히 중복 가능성이 있습니다.
객체 클래스를 먼저 살펴 보겠습니다. 우리는 객체 클래스가 Java 프로그램의 모든 클래스의 직접 또는 간접 부모 클래스이며 클래스 수준의 가장 높은 지점에 있음을 알고 있습니다. 많은 일반적인 메소드가 다음과 같이 우리가 말하고 싶은 해시 코드 메소드를 포함하여 객체 클래스에 정의됩니다.
공개 최종 기본 클래스 <?> getClass (); 공개 기본 int hashcode (); public boolean Equals (Object obj) {return (this == obj); } public String toString () {return getClass (). getName () + "@" + " + integer.toHexString (hashCode ()); }해시 코드 방법 앞에는 기본 수정자가 있으며, 이는 해시 코드 메소드가 비 Java 언어로 구현됨을 의미합니다. 특정 방법은 외부에서 구현되며 메모리 객체의 주소를 반환합니다.
많은 Java 클래스에서, 동등한 해시 코드 방법이 다시 작성됩니다. 이게 왜? 동일한 문자로 두 문자열을 정의하는 것과 같은 가장 일반적인 문자열 클래스는 비교할 때 원하는 결과가 동일해야합니다. 평등 및 해시 코드 메소드를 무시하지 않으면 두 객체의 메모리 주소가 다르기 때문에 동일하지 않습니다.
public int hashcode () {int h = hash; if (h == 0) {int off = 오프셋; char val [] = value; int len = count; for (int i = 0; i <len; i ++) {h = 31*h+val [off ++]; } 해시 = h; } 반환 h; }실제로이 코드는이 수학적 표현의 구현입니다.
S [0]*31^(N-1) + S [1]*31^(N-2) +… + S [N-1]
S [i]는 문자열의 i-th 문자이고 n은 문자열의 길이입니다. 그렇다면 왜 다른 숫자 대신 여기에서 31을 사용합니까? 효과적인 Java는 다음과 같이 말합니다. 31이 선택된 이유는 홀수 소수이기 때문입니다. 승수가 짝수 숫자이고 곱셈 오버 플로우가있는 경우, 2를 곱하는 것이 시프트 조작과 동일하기 때문에 정보가 손실됩니다. 소수를 사용하는 이점은 분명하지 않지만 해시 결과는 해당 결과를 계산하는 데 일반적으로 사용됩니다. 31은 더 나은 성능을 얻기 위해 곱셈 대신 시프트 및 뺄셈을 사용하는 좋은 기능을 가지고 있습니다. 31*i == (i << 5) -i. VMS는이 최적화를 자동으로 완료 할 수 있습니다.
보시다시피, 문자열 클래스는 해시 코드를 계산하기 위해 값 값을 매개 변수로 사용합니다. 즉, 동일한 값은 동일한 해시 코드 값을 갖습니다. 값 값이 동일하기 때문에 이해하기 쉽기 때문에 동등한 비교가 동일하면 동등한 메소드가 같으면 해시 코드가 같아야합니다. 다른 방법이 반드시 사실은 아닙니다. 동일한 해시 코드에 동일한 객체가 있어야한다고 보장하지는 않습니다.
좋은 해시 함수는 다음과 같아야합니다. 다른 물체에 대해 불평등 한 해시 코드를 생성합니다.
이상적인 경우, 해시 함수는 세트의 불평등 한 인스턴스를 가능한 모든 해시 코드에 균등하게 분배해야합니다. 이 이상적인 상황을 달성하는 것은 매우 어렵습니다. 적어도 Java는 그것을 달성하지 못했습니다. 해시 코드가 무작위로 생성되고 특정 규칙이있는 것을 알 수 있기 때문에 위의 수학적 방정식입니다. AA와 BB의 해시 코드는 동일합니다.
다음 코드 :
Public Class Main {public static void main (String [] args) {main m = new Main (); System.out.println (M); System.out.println (integer.tohexstring (m.hashcode ())); 문자열 a = "aa"; 문자열 b = "bb"; System.out.println (a.hashcode ()); System.out.println (b.hashcode ()); }}출력 결과 :
Main@2A139A55 2A139A55 2112 2112
일반적으로 동일한 함수를 다시 쓰면 해시 코드 함수를 다시 작성해야합니다. 이게 왜?
이 예를 살펴 보자. 간단한 클래스 직원을 만들어 봅시다.
공개 클래스 직원 {개인 정수 ID; 개인 문자열 firstName; 개인 문자열 마지막 이름; 개인 문자열 부서; 공개 정수 getId () {return id; } public void setId (정수 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 () {반환 부서; } public void setDepartment (문자열 부서) {this.department = 부서; }}위의 직원 클래스에는 매우 기본적인 속성과 게터 및 세터 만 있습니다. 이제 두 명의 직원을 비교 해야하는 상황을 고려하십시오.
public class EqualStest {public static void main (String [] args) {Employee e1 = new Employee (); 직원 E2 = 새로운 직원 (); e1.setID (100); e2.setid (100); // Console System.out.println (e1.equals (e2))에서 False를 인쇄합니다. }}위의 프로그램이 False를 출력한다는 것은 의심의 여지가 없지만 실제로 위의 두 개체는 직원을 통해 나타납니다. 실제 비즈니스 논리는 우리가 TRUE를 반환하기를 희망합니다.
이를 달성하려면 Equals 메소드를 다시 작성해야합니다.
public boolean equals (Object o) {if (o == null) {return false; } if (o == this) {return true; } if (getClass ()! = O.getClass ()) {return false; } 직원 E = (직원) o; return (this.getId () == e.getId ());} 이 메소드를 위의 클래스에 추가하면 eauqlstest가 true를 출력합니다.
그래서 우리는 끝났나요? 아니요, 테스트 방법을 변경하고 살펴 보겠습니다.
import java.util.hashset; import java.util.set; public class equalStest {public static void main (string [] args) {Employee e1 = new Employee (); 직원 E2 = New Employee (); e1.setId (100); e2.setId (100); prints 'teplitior.println (e1.print.println); = New Hashset <Employee> (); Employees.add (e1); Employec.Add (e2); // 두 개의 ObjectsSystem.out.println (직원);} 인쇄위의 프로그램은 두 가지 결과를 출력합니다. 두 직원 개체가 Return True와 같으면 하나의 객체 만 세트에 저장해야합니다. 문제는 무엇입니까?
두 번째 중요한 방법 hashcode ()를 잊어 버렸습니다. JDK의 Javadoc이 말했듯이, equals () 메소드를 다시 작성하면 hashcode () 메소드를 다시 작성해야합니다. 다음 방법을 추가하겠습니다. 프로그램이 올바르게 실행됩니다.
@override public int hashcode () {Final int Prime = 31; int result = 1; 결과 = prime * result + getId (); 반환 결과; }기억해야 할 것들
객체의 동일한 속성이 hashcode ()와 equals ()의 두 가지 방법을 생성하는 데 사용되는지 확인하십시오. 이 경우 직원 ID를 사용합니다.
eqauls 방법은 일관성이 있어야합니다 (객체가 수정되지 않은 경우 동일한 값을 반환해야합니다).
A.equals (b)만큼 언제나 A.HashCode ()는 B.HASHCODE ()와 같아야합니다.
둘 다 동시에 다시 작성해야합니다.
요약
위의 내용은 Java의 해시 코드 방법에 대한이 기사의 심층적 인 이해에 관한 것이며, 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!