หลักการแฮช
ก่อนอื่น ก่อนที่เราจะกำหนดรหัสแฮชของ Java เราต้องเข้าใจว่าการแฮชคืออะไรและมีไว้เพื่ออะไร การแฮชเป็นกระบวนการของการใช้ฟังก์ชันแฮชกับข้อมูลบางอย่าง ฟังก์ชันแฮชเป็นเพียงฟังก์ชันทางคณิตศาสตร์ ไม่ต้องกังวลกับเรื่องนี้! “คณิตศาสตร์” ไม่ได้หมายความว่า “ซับซ้อน” เสมอไป ในที่นี้หมายความว่าเรามีข้อมูลบางส่วนและกฎบางอย่างที่แมปข้อมูลเป็นชุดอักขระ (รหัส) ตัวอย่างเช่น อาจเป็นรหัสตัวเลขฐานสิบหก เรามีข้อมูลขนาดใดก็ได้ที่อินพุต และใช้ฟังก์ชันแฮชกับข้อมูลนั้น ที่เอาต์พุต เราได้รับข้อมูลขนาดคงที่ เช่น 32 ตัวอักษร โดยปกติแล้ว ฟังก์ชันประเภทนี้จะแปลงข้อมูลขนาดใหญ่ให้เป็นค่าจำนวนเต็มขนาดเล็ก ผลลัพธ์ของการทำงานของฟังก์ชันนี้เรียกว่ารหัสแฮช ฟังก์ชันแฮชถูกใช้อย่างแพร่หลายในการเข้ารหัส และบางพื้นที่ด้วยเช่นกัน ฟังก์ชันแฮชอาจแตกต่างกัน
- วัตถุเฉพาะมีรหัสแฮชเฉพาะ
- หากวัตถุสองชิ้นมีค่าเท่ากัน รหัสแฮชของวัตถุทั้งสองจะเหมือนกัน สิ่งที่ตรงกันข้ามไม่เป็นความจริง
- หากรหัสแฮชต่างกันแสดงว่าวัตถุนั้นไม่เท่ากันอย่างแน่นอน
- วัตถุที่แตกต่างกันอาจมีรหัสแฮชเดียวกัน อย่างไรก็ตาม มันเป็นเหตุการณ์ที่ไม่น่าเกิดขึ้นมากนัก ณ จุดนี้ เรามีการปะทะกัน สถานการณ์ที่เราอาจสูญเสียข้อมูล
ฟังก์ชันแฮชที่ "เหมาะสม" ช่วยลดความน่าจะเป็นของการชนกันให้เหลือน้อยที่สุด
แฮชโค้ดในภาษาจาวา
ในฟังก์ชันแฮช Java มักจะเชื่อมต่อกับ
เมธอด hashCode( ) ผลลัพธ์ของการใช้ฟังก์ชันแฮชกับอ็อบเจกต์คือแฮชโค้ด ทุกวัตถุ Java มีรหัสแฮช โดยทั่วไป Hash Code คือตัวเลขที่คำนวณโดย
hashCode() วิธีการของ
Object
คลาส โดยปกติแล้ว โปรแกรมเมอร์จะแทนที่เมธอดนี้สำหรับออบเจกต์ของตน เช่นเดียวกับ เมธอด
hashCode() the
equals()เพื่อการประมวลผลข้อมูลเฉพาะอย่างมีประสิทธิภาพมากขึ้น เมธอด
hashCode()ส่งคืนค่า int (4 ไบต์) ซึ่งเป็นการแสดงตัวเลขของวัตถุ ตัวอย่างเช่น แฮชโค้ดนี้ถูกใช้โดยคอลเล็กชันเพื่อการจัดเก็บข้อมูลที่มีประสิทธิภาพมากขึ้น และด้วยเหตุนี้ การเข้าถึงจึงเร็วขึ้น โดยค่าเริ่มต้น
hashCode()ฟังก์ชันสำหรับออบเจกต์จะส่งคืนจำนวนเซลล์หน่วยความจำที่เก็บออบเจ็กต์ไว้ ดังนั้นหากไม่มีการเปลี่ยนแปลงรหัสแอปพลิเคชัน ฟังก์ชันควรคืนค่าเดิม หากโค้ดเปลี่ยนแปลงเล็กน้อย ค่าแฮชโค้ดก็จะเปลี่ยนไปด้วย แฮชโค้ดที่ใช้ใน Java คืออะไร ประการแรก แฮชโค้ด Java ช่วยให้โปรแกรมทำงานได้เร็วขึ้น ตัวอย่างเช่น หากเราเปรียบเทียบวัตถุสองชิ้น
o1
กับวัตถุ
o2
บางประเภท การดำเนินการ
o1.equals(o2)
จะใช้เวลามากกว่า 20 เท่า
o1.hashCode() == o2.hashCode()
Java เท่ากับ ()
ในคลาสพาเรนต์
Object
ควบคู่ไปกับ เมธอด
hashCode()ยังมี
เท่ากับ ()ฟังก์ชันที่ใช้ตรวจสอบความเท่าเทียมกันของสองอ็อบเจกต์ การใช้งานเริ่มต้นของฟังก์ชันนี้เพียงตรวจสอบการเชื่อมโยงของวัตถุสองชิ้นเพื่อความเท่าเทียมกัน
เท่ากับ ()และ
hashCode ()มีสัญญา ดังนั้นหากคุณแทนที่หนึ่งในนั้น คุณควรแทนที่อีกอัน เพื่อไม่ให้สัญญานี้ผิด
การใช้ hashCode() วิธีการ
ตัวอย่าง
มาสร้างคลาสCharacter
ด้วยฟิลด์เดียว —
ชื่อ หลังจากนั้น เราสร้างอ็อบเจกต์ คลาส
Character สอง รายการ
character1และ
character2และตั้งชื่อให้เหมือนกัน หากเราใช้ค่าเริ่มต้น
hashCode()และ
เท่ากับ()ของ คลาส
Objectเราจะได้วัตถุที่แตกต่างกันและไม่เท่ากัน นั่นคือวิธีการทำงานของ hashcode ใน Java พวกเขาจะมีรหัสแฮชที่แตกต่างกันเนื่องจากอยู่ในเซลล์หน่วยความจำที่แตกต่างกันและ ผลลัพธ์ของการดำเนินการ
เท่ากับ ()จะเป็นเท็จ
import java.util.Objects;
public class Character {
private String Name;
public Character(String name) {
Name = name;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public static void main(String[] args) {
Character character1 = new Character("Arnold");
System.out.println(character1.getName());
System.out.println(character1.hashCode());
Character character2 = new Character("Arnold");
System.out.println(character2.getName());
System.out.println(character2.hashCode());
System.out.println(character2.equals(character1));
}
}
ผลลัพธ์ของการเรียกใช้โปรแกรม:
Arnold
1595428806
Arnold
1072408673
false
ตัวเลข 10 หลักสองตัวในคอนโซลคือรหัสแฮช จะทำอย่างไรถ้าเราต้องการให้วัตถุเท่ากันหากมีชื่อเหมือนกัน เราควรทำอย่างไร? คำตอบ: เราควรแทนที่
เมธอด hashCode()และ
equals()ของ คลาส
Objectสำหรับคลาส
Character ของเรา เราสามารถทำได้โดยอัตโนมัติใน IDEA IDE เพียงกด
alt + insertบนแป้นพิมพ์ของคุณแล้วเลือก
Generate -> equals() และ hashCode( )
![Java hashCode() คืออะไร - 2]()
ในกรณีตัวอย่างของเรา เรามีโค้ดถัดไป:
import java.util.Objects;
public class Character {
private String Name;
public Character(String name) {
Name = name;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Character)) return false;
Character character = (Character) o;
return getName() != null ? getName().equals(character.getName()) : character.getName() == null;
}
@Override
public int hashCode() {
return getName() != null ? getName().hashCode() : 0;
}
public static void main(String[] args) {
Character character1 = new Character("Arnold");
System.out.println(character1.getName());
System.out.println(character1.hashCode());
Character character2 = new Character("Arnold");
System.out.println(character2.getName());
System.out.println(character2.hashCode());
System.out.println(character2.equals(character1));
}
}
ผลลัพธ์ของการเรียกใช้รหัสนี้:
Arnold
1969563338
Arnold
1969563338
true
ตอนนี้โปรแกรมระบุว่าวัตถุของเราเท่ากันและมีรหัสแฮชเหมือนกัน
ตัวอย่างแฮชโค้ด Java:
hashCode ของคุณเอง () และเท่ากับ ()
คุณยังสามารถสร้างการสำนึก เท่ากับ ()และ
hashCode ()ของคุณเองแต่โปรดระวังและอย่าลืมลดการชนกันของรหัสแฮช นี่คือตัวอย่าง
เมธอด hashCode()และ
equals() ของเราเอง ใน คลาส
Student :
import java.util.Date;
public class Student {
String surname;
String name;
String secondName;
Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases
public Student(String surname, String name, String secondName, Date birthday ){
this.surname = surname;
this.name = name;
this.secondName = secondName;
this.birthday = birthday == null ? 0 : birthday.getTime();
}
//Java hashcode example
@Override
public int hashCode(){
//TODO: check for nulls
//return surname.hashCode() ^ name.hashCode() ^ secondName.hashCode() ^ (birthday.hashCode());
return (surname + name + secondName + birthday).hashCode();
}
@Override
public boolean equals(Object other_) {
Student other = (Student)other_;
return (surname == null || surname.equals(other.surname) )
&& (name == null || name.equals(other.name))
&& (secondName == null || secondName.equals(other.secondName))
&& (birthday == null || birthday.equals(other.birthday));
}
}
และ ชั้นเรียน
หลักเพื่อสาธิตการทำงานของพวกเขา:
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
public class Main {
static HashMap<Student, Integer> cache = new HashMap<Student, Integer>(); // <person, targetPriority>
public static void main(String[] args) {
Student sarah1 = new Student("Sarah","Connor", "Jane", null);
Student sarah2 = new Student("Sarah","Connor", "Jane", new Date(1970, 01-1, 01));
Student sarah3 = new Student("Sarah","Connor", "Jane", new Date(1959, 02-1, 28)); // date not exists
Student john = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
Student johnny = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
System.out.println(john.hashCode());
System.out.println(johnny.hashCode());
System.out.println(sarah1.hashCode());
System.out.println();
cache.put(sarah1, 1);
cache.put(sarah2, 2);
cache.put(sarah3, 3);
System.out.println(new Date(sarah1.birthday));
System.out.println();
cache.put(john, 5);
System.out.println(cache.get(john));
System.out.println(cache.get(johnny));
cache.put(johnny, 7);
System.out.println(cache.get(john));
System.out.println(cache.get(johnny));
}
}
แฮชโค้ดใช้สำหรับอะไร
ประการแรก แฮชโค้ดช่วยให้โปรแกรมทำงานได้เร็วขึ้น ตัวอย่างเช่น หากเราเปรียบเทียบวัตถุสองชิ้น
o1
และ
o2
บางประเภท การดำเนินการ
o1.equals(o2)
จะใช้เวลามากกว่า o1.hashCode() == o2.hashCode() ประมาณ 20 เท่า ในหลักการแฮชของ Java นั้นอยู่เบื้องหลังคอลเล็กชันยอด นิยม เช่น
HashMap ,
HashSetและ
HashTable
บทสรุป
วัตถุ Java ทุกตัวมีเมธอด
hashCode()และ
เท่ากับ()ที่สืบทอดมาจากคลาส
อ็อบเจกต์ เพื่อให้ได้กลไกความเท่าเทียมกันที่ใช้งานได้ดี คุณควรแทนที่เมธอด
hashcode()และ
equals()สำหรับคลาสของคุณเอง การใช้แฮชโค้ดทำให้โปรแกรมทำงานเร็วขึ้น
GO TO FULL VERSION